Files
rust-libp2p/protocols/kad/src/behaviour/test.rs

822 lines
31 KiB
Rust
Raw Normal View History

// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#![cfg(test)]
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
use super::*;
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
use crate::{ALPHA_VALUE, K_VALUE};
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
use crate::kbucket::Distance;
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
use crate::record::store::MemoryStore;
use futures::{
prelude::*,
executor::block_on,
future::poll_fn,
};
use libp2p_core::{
PeerId,
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
Transport,
identity,
transport::MemoryTransport,
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
multiaddr::{Protocol, Multiaddr, multiaddr},
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
muxing::StreamMuxerBox,
upgrade
};
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
use libp2p_secio::SecioConfig;
use libp2p_swarm::Swarm;
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
use libp2p_yamux as yamux;
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
use quickcheck::*;
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
use rand::{Rng, random, thread_rng};
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
use std::{collections::{HashSet, HashMap}, io, num::NonZeroUsize, u64};
use multihash::{wrap, Code, Multihash};
2020-03-25 18:11:21 +03:00
use libp2p_core::identity::ed25519;
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
type TestSwarm = Swarm<Kademlia<MemoryStore>>;
2020-04-21 19:54:30 +03:00
fn build_node() -> (ed25519::Keypair, Multiaddr, TestSwarm) {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
build_node_with_config(Default::default())
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
2020-04-21 19:54:30 +03:00
fn build_node_with_config(cfg: KademliaConfig) -> (ed25519::Keypair, Multiaddr, TestSwarm) {
let ed25519_key = ed25519::Keypair::generate();
let local_key = identity::Keypair::Ed25519(ed25519_key.clone());
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let local_public_key = local_key.public();
let transport = MemoryTransport::default()
.upgrade(upgrade::Version::V1)
.authenticate(SecioConfig::new(local_key))
.multiplex(yamux::Config::default())
.map(|(p, m), _| (p, StreamMuxerBox::new(m)))
.map_err(|e| -> io::Error { panic!("Failed to create transport: {:?}", e); })
.boxed();
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let local_id = local_public_key.clone().into_peer_id();
let store = MemoryStore::new(local_id.clone());
let trust = TrustGraph::new(Vec::new());
let behaviour = Kademlia::with_config(ed25519_key.clone(), local_id.clone(), store, cfg.clone(), trust);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarm = Swarm::new(transport, behaviour, local_id);
let address: Multiaddr = Protocol::Memory(random::<u64>()).into();
Swarm::listen_on(&mut swarm, address.clone()).unwrap();
(ed25519_key, address, swarm)
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
}
/// Builds swarms, each listening on a port. Does *not* connect the nodes together.
2020-04-21 19:54:30 +03:00
fn build_nodes(num: usize) -> Vec<(ed25519::Keypair, Multiaddr, TestSwarm)> {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
build_nodes_with_config(num, Default::default())
}
/// Builds swarms, each listening on a port. Does *not* connect the nodes together.
2020-04-21 19:54:30 +03:00
fn build_nodes_with_config(num: usize, cfg: KademliaConfig) -> Vec<(ed25519::Keypair, Multiaddr, TestSwarm)> {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
(0..num).map(|_| build_node_with_config(cfg.clone())).collect()
}
2020-04-21 19:54:30 +03:00
fn build_connected_nodes(total: usize, step: usize) -> Vec<(ed25519::Keypair, Multiaddr, TestSwarm)> {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
build_connected_nodes_with_config(total, step, Default::default())
}
fn build_connected_nodes_with_config(total: usize, step: usize, cfg: KademliaConfig)
2020-04-21 19:54:30 +03:00
-> Vec<(ed25519::Keypair, Multiaddr, TestSwarm)>
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
{
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_nodes_with_config(total, cfg);
let swarm_ids: Vec<_> = swarms.iter()
2020-04-20 19:34:21 +03:00
.map(|(_, addr, swarm)| (addr.clone(), Swarm::local_peer_id(swarm).clone()))
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect();
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let mut i = 0;
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
for (j, (addr, peer_id)) in swarm_ids.iter().enumerate().skip(1) {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
if i < swarm_ids.len() {
2020-03-25 18:11:21 +03:00
let public = swarms[i].0.public();
2020-04-21 19:54:30 +03:00
swarms[i].2.add_address(peer_id, addr.clone(), public);
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
}
if j % step == 0 {
i += step;
}
}
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
swarms
}
fn build_fully_connected_nodes_with_config(total: usize, cfg: KademliaConfig)
2020-04-20 19:34:21 +03:00
-> Vec<(ed25519::Keypair, Multiaddr, TestSwarm)>
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
{
let mut swarms = build_nodes_with_config(total, cfg);
let swarm_addr_and_peer_id: Vec<_> = swarms.iter()
2020-04-21 19:54:30 +03:00
.map(|(kp, addr, swarm)| (kp.public().clone(), addr.clone(), Swarm::local_peer_id(swarm).clone()))
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect();
2020-04-21 19:54:30 +03:00
for (_, _addr, swarm) in swarms.iter_mut() {
2020-04-20 19:34:21 +03:00
for (public, addr, peer) in &swarm_addr_and_peer_id {
2020-04-21 19:54:30 +03:00
swarm.add_address(&peer, addr.clone(), public.clone());
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
}
}
swarms
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
}
fn random_multihash() -> Multihash {
wrap(Code::Sha2_256, &thread_rng().gen::<[u8; 32]>())
}
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
#[test]
fn bootstrap() {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
fn run(rng: &mut impl Rng) {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let num_total = rng.gen_range(2, 20);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
// When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query
// at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known
// nodes will not be considered. Given that no other node is aware of them, they would be
// lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than
// ALPHA_VALUE.
let num_group = rng.gen_range(1, (num_total % ALPHA_VALUE.get()) + 2);
let mut swarms = build_connected_nodes(num_total, num_group).into_iter()
2020-04-21 19:54:30 +03:00
.map(|(_, _a, s)| s)
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect::<Vec<_>>();
let swarm_ids: Vec<_> = swarms.iter().map(Swarm::local_peer_id).cloned().collect();
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
2020-04-21 19:54:30 +03:00
swarms[0].bootstrap();
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
// Expected known peers
let expected_known = swarm_ids.iter().skip(1).cloned().collect::<HashSet<_>>();
// Run test
block_on(
poll_fn(move |ctx| {
2020-04-21 19:54:30 +03:00
for (i, swarm) in swarms.iter_mut().enumerate() {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::BootstrapResult(Ok(ok)))) => {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert_eq!(i, 0);
assert_eq!(ok.peer, swarm_ids[0]);
let known = swarm.kbuckets.iter()
.map(|e| e.node.key.preimage().clone())
.collect::<HashSet<_>>();
assert_eq!(expected_known, known);
return Poll::Ready(())
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
}
}
}
Poll::Pending
})
)
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
}
let mut rng = thread_rng();
for _ in 0 .. 10 {
run(&mut rng)
}
}
#[test]
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
fn query_iter() {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
fn distances<K>(key: &kbucket::Key<K>, peers: Vec<PeerId>) -> Vec<Distance> {
Improve XOR metric. (#1108) There are two issues with the current definition and use of Kademlia's XOR metric: 1. The distance is currently equated with the bucket index, i.e. `distance(a,b) - 1` is the index of the bucket into which either peer is put by the other. The result is a metric that is not unidirectional, as defined in the Kademlia paper and as implemented in e.g. libp2p-go and libp2p-js, which is to interpret the result of the XOR as an integer in its entirety. 2. The current `KBucketsPeerId` trait and its instances allow computing distances between types with differing bit lengths as well as between types that hash all inputs again (i.e. `KadHash`) and "plain" `PeerId`s or `Multihash`es. This can result in computed distances that are either incorrect as per the requirement of the libp2p specs that all distances are to be computed from the XOR of the SHA256 of the input keys, or even fall outside of the image of the metric used for the `KBucketsTable`. In the latter case, such distances are not currently used as a bucket index - they can only occur in the context of comparing distances for the purpose of sorting peers - but that still seems undesirable. These issues are addressed here as follows: * Unidirectionality of the XOR metric is restored by keeping the "full" integer representation of the bitwise XOR. The result is an XOR metric as defined in the paper. This also opens the door to avoiding the "full table scan" when searching for the keys closest to a given key - the ideal order in which to visit the buckets can be computed with the help of the distance bit string. * As a simplification and to make it easy to "do the right thing", the XOR metric is only defined on an opaque `kbucket::Key` type, partially derived from the current `KadHash`. `KadHash` and `KBucketsPeerId` are removed.
2019-05-17 17:27:57 +02:00
peers.into_iter()
.map(kbucket::Key::from)
.map(|k| k.distance(key))
.collect()
}
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
fn run(rng: &mut impl Rng) {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let num_total = rng.gen_range(2, 20);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_connected_nodes(num_total, 1).into_iter()
2020-04-21 19:54:30 +03:00
.map(|(_, _a, s)| s)
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect::<Vec<_>>();
let swarm_ids: Vec<_> = swarms.iter().map(Swarm::local_peer_id).cloned().collect();
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
// Ask the first peer in the list to search a random peer. The search should
// propagate forwards through the list of peers.
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
let search_target = PeerId::random();
let search_target_key = kbucket::Key::new(search_target.clone());
2020-04-21 19:54:30 +03:00
swarms[0].get_closest_peers(search_target.clone());
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
// Set up expectations.
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let expected_swarm_id = swarm_ids[0].clone();
let expected_peer_ids: Vec<_> = swarm_ids.iter().skip(1).cloned().collect();
Improve XOR metric. (#1108) There are two issues with the current definition and use of Kademlia's XOR metric: 1. The distance is currently equated with the bucket index, i.e. `distance(a,b) - 1` is the index of the bucket into which either peer is put by the other. The result is a metric that is not unidirectional, as defined in the Kademlia paper and as implemented in e.g. libp2p-go and libp2p-js, which is to interpret the result of the XOR as an integer in its entirety. 2. The current `KBucketsPeerId` trait and its instances allow computing distances between types with differing bit lengths as well as between types that hash all inputs again (i.e. `KadHash`) and "plain" `PeerId`s or `Multihash`es. This can result in computed distances that are either incorrect as per the requirement of the libp2p specs that all distances are to be computed from the XOR of the SHA256 of the input keys, or even fall outside of the image of the metric used for the `KBucketsTable`. In the latter case, such distances are not currently used as a bucket index - they can only occur in the context of comparing distances for the purpose of sorting peers - but that still seems undesirable. These issues are addressed here as follows: * Unidirectionality of the XOR metric is restored by keeping the "full" integer representation of the bitwise XOR. The result is an XOR metric as defined in the paper. This also opens the door to avoiding the "full table scan" when searching for the keys closest to a given key - the ideal order in which to visit the buckets can be computed with the help of the distance bit string. * As a simplification and to make it easy to "do the right thing", the XOR metric is only defined on an opaque `kbucket::Key` type, partially derived from the current `KadHash`. `KadHash` and `KBucketsPeerId` are removed.
2019-05-17 17:27:57 +02:00
let mut expected_distances = distances(&search_target_key, expected_peer_ids.clone());
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
expected_distances.sort();
// Run test
block_on(
poll_fn(move |ctx| {
2020-04-21 19:54:30 +03:00
for (i, swarm) in swarms.iter_mut().enumerate() {
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetClosestPeersResult(Ok(ok)))) => {
assert_eq!(&ok.key[..], search_target.as_bytes());
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
assert_eq!(swarm_ids[i], expected_swarm_id);
assert_eq!(swarm.queries.size(), 0);
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert!(expected_peer_ids.iter().all(|p| ok.peers.contains(p)));
let key = kbucket::Key::new(ok.key);
assert_eq!(expected_distances, distances(&key, ok.peers));
return Poll::Ready(());
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
}
}
}
Poll::Pending
})
)
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
}
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let mut rng = thread_rng();
for _ in 0 .. 10 {
run(&mut rng)
}
}
#[test]
fn unresponsive_not_returned_direct() {
// Build one node. It contains fake addresses to non-existing nodes. We ask it to find a
// random peer. We make sure that no fake address is returned.
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_nodes(1).into_iter()
2020-04-21 19:54:30 +03:00
.map(|(kp, _a, s)| (kp, s))
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect::<Vec<_>>();
// Add fake addresses.
for _ in 0 .. 10 {
2020-03-25 18:11:21 +03:00
let public0 = swarms[0].0.public();
swarms[0].1.add_address(&PeerId::random(), Protocol::Udp(10u16).into(), public0);
}
// Ask first to search a random value.
let search_target = PeerId::random();
2020-03-25 18:11:21 +03:00
swarms[0].1.get_closest_peers(search_target.clone());
block_on(
poll_fn(move |ctx| {
2020-03-25 18:11:21 +03:00
for (_, swarm) in &mut swarms {
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetClosestPeersResult(Ok(ok)))) => {
assert_eq!(&ok.key[..], search_target.as_bytes());
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert_eq!(ok.peers.len(), 0);
return Poll::Ready(());
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
}
}
}
Poll::Pending
})
)
}
#[test]
fn unresponsive_not_returned_indirect() {
// Build two nodes. Node #2 knows about node #1. Node #1 contains fake addresses to
Fix self-dialing in Kademlia. (#1097) * Fix self-dialing in Kademlia. Addresses https://github.com/libp2p/rust-libp2p/issues/341 which is the cause for one of the observations made in https://github.com/libp2p/rust-libp2p/issues/1053. However, the latter is not assumed to be fully addressed by these changes and needs further investigation. Currently, whenever a search for a key yields a response containing the initiating peer as one of the closest peers known to the remote, the local node would attempt to dial itself. That attempt is ignored by the Swarm, but the Kademlia behaviour now believes it still has a query ongoing which is always doomed to time out. That timeout delays successful completion of the query. Hence, any query where a remote responds with the ID of the local node takes at least as long as the `rpc_timeout` to complete, which possibly affects almost all queries in smaller clusters where every node knows about every other. This problem is fixed here by ensuring that Kademlia never tries to dial the local node. Furthermore, `Discovered` events are no longer emitted for the local node and it is not inserted into the `untrusted_addresses` from discovery, as described in #341. This commit also includes a change to the condition for freezing / terminating a Kademlia query upon receiving a response. Specifically, the condition is tightened such that it only applies if in addition to `parallelism` consecutive responses that failed to yield a peer closer to the target, the last response must also either not have reported any new peer or the number of collected peers has already reached the number of desired results. In effect, a Kademlia query now tries harder to actually return `k` closest peers. Tests have been refactored and expanded. * Add another comment.
2019-05-02 21:43:29 +02:00
// non-existing nodes. We ask node #2 to find a random peer. We make sure that no fake address
// is returned.
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_nodes(2);
// Add fake addresses to first.
for _ in 0 .. 10 {
2020-03-25 18:11:21 +03:00
let public0 = swarms[0].0.public();
2020-04-21 19:54:30 +03:00
swarms[0].2.add_address(&PeerId::random(), multiaddr![Udp(10u16)], public0);
}
// Connect second to first.
2020-04-21 19:54:30 +03:00
let first_peer_id = Swarm::local_peer_id(&swarms[0].2).clone();
let first_address = swarms[0].1.clone();
2020-03-25 18:11:21 +03:00
let public1 = swarms[1].0.public();
2020-04-21 19:54:30 +03:00
swarms[1].2.add_address(&first_peer_id, first_address, public1);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
// Drop the swarm addresses.
2020-04-21 19:54:30 +03:00
let mut swarms = swarms.into_iter().map(|(_, _addr, swarm)| swarm).collect::<Vec<_>>();
// Ask second to search a random value.
let search_target = PeerId::random();
2020-04-21 19:54:30 +03:00
swarms[1].get_closest_peers(search_target.clone());
block_on(
poll_fn(move |ctx| {
2020-04-21 19:54:30 +03:00
for swarm in &mut swarms {
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetClosestPeersResult(Ok(ok)))) => {
assert_eq!(&ok.key[..], search_target.as_bytes());
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert_eq!(ok.peers.len(), 1);
assert_eq!(ok.peers[0], first_peer_id);
return Poll::Ready(());
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
}
}
}
Poll::Pending
})
)
}
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
#[test]
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
fn get_record_not_found() {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_nodes(3);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let swarm_ids: Vec<_> = swarms.iter()
2020-04-21 19:54:30 +03:00
.map(|(_, _addr, swarm)| Swarm::local_peer_id(swarm))
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.cloned()
.collect();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
2020-03-25 18:11:21 +03:00
let public0 = swarms[0].0.public();
let public1 = swarms[1].0.public();
2020-04-21 19:54:30 +03:00
let (second, third) = (swarms[1].1.clone(), swarms[2].1.clone());
swarms[0].2.add_address(&swarm_ids[1], second, public0);
swarms[1].2.add_address(&swarm_ids[2], third, public1);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
// Drop the swarm addresses.
2020-04-21 19:54:30 +03:00
let mut swarms = swarms.into_iter().map(|(_, _addr, swarm)| swarm).collect::<Vec<_>>();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
let target_key = record::Key::from(random_multihash());
2020-04-21 19:54:30 +03:00
swarms[0].get_record(&target_key, Quorum::One);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
block_on(
poll_fn(move |ctx| {
2020-04-21 19:54:30 +03:00
for swarm in &mut swarms {
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetRecordResult(Err(e)))) => {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
if let GetRecordError::NotFound { key, closest_peers, } = e {
assert_eq!(key, target_key);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
assert_eq!(closest_peers.len(), 2);
assert!(closest_peers.contains(&swarm_ids[1]));
assert!(closest_peers.contains(&swarm_ids[2]));
return Poll::Ready(());
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
} else {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
panic!("Unexpected error result: {:?}", e);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
}
}
Poll::Pending
})
)
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
/// A node joining a fully connected network via a single bootnode should be able to put a record to
/// the X closest nodes of the network where X is equal to the configured replication factor.
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
#[test]
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
fn put_record() {
fn prop(replication_factor: usize, records: Vec<Record>) {
let replication_factor = NonZeroUsize::new(replication_factor % (K_VALUE.get() / 2) + 1).unwrap();
let num_total = replication_factor.get() * 2;
let mut config = KademliaConfig::default();
config.set_replication_factor(replication_factor);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = {
let mut fully_connected_swarms = build_fully_connected_nodes_with_config(
num_total - 1,
config.clone(),
);
let mut single_swarm = build_node_with_config(config);
2020-04-21 19:54:30 +03:00
single_swarm.2.add_address(
Swarm::local_peer_id(&fully_connected_swarms[0].2),
fully_connected_swarms[0].1.clone(),
fully_connected_swarms[0].0.public(),
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
);
let mut swarms = vec![single_swarm];
swarms.append(&mut fully_connected_swarms);
// Drop the swarm addresses.
2020-04-21 19:54:30 +03:00
swarms.into_iter().map(|(_, _addr, swarm)| swarm).collect::<Vec<_>>()
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
};
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let records = records.into_iter()
.take(num_total)
.map(|mut r| {
// We don't want records to expire prematurely, as they would
// be removed from storage and no longer replicated, but we still
// want to check that an explicitly set expiration is preserved.
r.expires = r.expires.map(|t| t + Duration::from_secs(60));
(r.key.clone(), r)
})
.collect::<HashMap<_,_>>();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
for r in records.values() {
2020-04-21 19:54:30 +03:00
swarms[0].put_record(r.clone(), Quorum::All);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// Each test run republishes all records once.
let mut republished = false;
// The accumulated results for one round of publishing.
let mut results = Vec::new();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
block_on(
poll_fn(move |ctx| loop {
// Poll all swarms until they are "Pending".
2020-04-21 19:54:30 +03:00
for swarm in &mut swarms {
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::PutRecordResult(res))) |
Poll::Ready(Some(KademliaEvent::RepublishRecordResult(res))) => {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
match res {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
Err(e) => panic!("{:?}", e),
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
Ok(ok) => {
assert!(records.contains_key(&ok.key));
let record = swarm.store.get(&ok.key).unwrap();
results.push(record.into_owned());
}
}
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
}
}
// All swarms are Pending and not enough results have been collected
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// so far, thus wait to be polled again for further progress.
if results.len() != records.len() {
return Poll::Pending
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// Consume the results, checking that each record was replicated
// correctly to the closest peers to the key.
while let Some(r) = results.pop() {
let expected = records.get(&r.key).unwrap();
assert_eq!(r.key, expected.key);
assert_eq!(r.value, expected.value);
assert_eq!(r.expires, expected.expires);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
assert_eq!(r.publisher.as_ref(), Some(Swarm::local_peer_id(&swarms[0])));
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let key = kbucket::Key::new(r.key.clone());
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut expected = swarms.iter()
.skip(1)
.map(Swarm::local_peer_id)
.cloned()
.collect::<Vec<_>>();
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
expected.sort_by(|id1, id2|
kbucket::Key::new(id1.clone()).distance(&key).cmp(
&kbucket::Key::new(id2.clone()).distance(&key)));
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let expected = expected
.into_iter()
.take(replication_factor.get())
.collect::<HashSet<_>>();
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let actual = swarms.iter()
.skip(1)
2020-04-21 19:54:30 +03:00
.filter_map(|swarm|
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
if swarm.store.get(key.preimage()).is_some() {
Some(Swarm::local_peer_id(swarm).clone())
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
} else {
None
})
.collect::<HashSet<_>>();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
assert_eq!(actual.len(), replication_factor.get());
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let actual_not_expected = actual.difference(&expected)
.collect::<Vec<&PeerId>>();
assert!(
actual_not_expected.is_empty(),
"Did not expect records to be stored on nodes {:?}.",
actual_not_expected,
);
let expected_not_actual = expected.difference(&actual)
.collect::<Vec<&PeerId>>();
assert!(expected_not_actual.is_empty(),
"Expected record to be stored on nodes {:?}.",
expected_not_actual,
);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
if republished {
2020-04-21 19:54:30 +03:00
assert_eq!(swarms[0].store.records().count(), records.len());
assert_eq!(swarms[0].queries.size(), 0);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
for k in records.keys() {
2020-04-21 19:54:30 +03:00
swarms[0].store.remove(&k);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
2020-04-21 19:54:30 +03:00
assert_eq!(swarms[0].store.records().count(), 0);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// All records have been republished, thus the test is complete.
return Poll::Ready(());
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// Tell the replication job to republish asap.
2020-04-21 19:54:30 +03:00
swarms[0].put_record_job.as_mut().unwrap().asap(true);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
republished = true;
})
)
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
QuickCheck::new().tests(3).quickcheck(prop as fn(_,_) -> _)
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
#[test]
fn get_value() {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_nodes(3);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
// Let first peer know of second peer and second peer know of third peer.
for i in 0..2 {
2020-04-21 19:54:30 +03:00
let (peer_id, public, address) = (Swarm::local_peer_id(&swarms[i+1].2).clone(), swarms[i+1].0.public(), swarms[i+1].1.clone());
swarms[i].2.add_address(&peer_id, address, public);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
}
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
// Drop the swarm addresses.
2020-04-21 19:54:30 +03:00
let mut swarms = swarms.into_iter().map(|(kp, _addr, swarm)| (kp, swarm)).collect::<Vec<_>>();
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let record = Record::new(random_multihash(), vec![4,5,6]);
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
2020-03-25 18:11:21 +03:00
swarms[1].1.store.put(record.clone()).unwrap();
swarms[0].1.get_record(&record.key, Quorum::One);
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
block_on(
poll_fn(move |ctx| {
2020-03-25 18:11:21 +03:00
for (_, swarm) in &mut swarms {
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetRecordResult(Ok(ok)))) => {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert_eq!(ok.records.len(), 1);
assert_eq!(ok.records.first(), Some(&record));
return Poll::Ready(());
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
}
}
Poll::Pending
})
)
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
#[test]
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
fn get_value_many() {
// TODO: Randomise
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let num_nodes = 12;
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = build_connected_nodes(num_nodes, 3).into_iter()
2020-04-21 19:54:30 +03:00
.map(|(_kp, _addr, swarm)| swarm)
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
.collect::<Vec<_>>();
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
let num_results = 10;
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
let record = Record::new(random_multihash(), vec![4,5,6]);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
for i in 0 .. num_nodes {
2020-04-21 19:54:30 +03:00
swarms[i].store.put(record.clone()).unwrap();
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let quorum = Quorum::N(NonZeroUsize::new(num_results).unwrap());
2020-04-21 19:54:30 +03:00
swarms[0].get_record(&record.key, quorum);
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
block_on(
poll_fn(move |ctx| {
2020-04-21 19:54:30 +03:00
for swarm in &mut swarms {
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::GetRecordResult(Ok(ok)))) => {
Kademlia: Address some TODOs - Refactoring - API updates. (#1174) * Address some TODOs, refactor queries and public API. The following left-over issues are addressed: * The key for FIND_NODE requests is generalised to any Multihash, instead of just peer IDs. * All queries get a (configurable) timeout. * Finishing queries as soon as enough results have been received is simplified to avoid code duplication. * No more panics in provider-API-related code paths. The provider API is however still untested and (I think) still incomplete (e.g. expiration of provider records). * Numerous smaller TODOs encountered in the code. The following public API changes / additions are made: * Introduce a `KademliaConfig` with new configuration options for the replication factor and query timeouts. * Rename `find_node` to `get_closest_peers`. * Rename `get_value` to `get_record` and `put_value` to `put_record`, introducing a `Quorum` parameter for both functions, replacing the existing `num_results` parameter with clearer semantics. * Rename `add_providing` to `start_providing` and `remove_providing` to `stop_providing`. * Add a `bootstrap` function that implements a (almost) standard Kademlia bootstrapping procedure. * Rename `KademliaOut` to `KademliaEvent` with an updated list of constructors (some renaming). All events that report query results now report a `Result` to uniformly permit reporting of errors. The following refactorings are made: * Introduce some constants. * Consolidate `query.rs` and `write.rs` behind a common query interface to reduce duplication and facilitate better code reuse, introducing the notion of a query peer iterator. `query/peers/closest.rs` contains the code that was formerly in `query.rs`. `query/peers/fixed.rs` contains a modified variant of `write.rs` (which is removed). The new `query.rs` provides an interface for working with a collection of queries, taking over some code from `behaviour.rs`. * Reduce code duplication in tests and use the current_thread runtime for polling swarms to avoid spurious errors in the test output due to aborted connections when a test finishes prematurely (e.g. because a quorum of results has been collected). * Some additions / improvements to the existing tests. * Fix test. * Fix rebase. * Tweak kad-ipfs example. * Incorporate some feedback. * Provide easy access and conversion to keys in error results.
2019-07-03 16:16:25 +02:00
assert_eq!(ok.records.len(), num_results);
assert_eq!(ok.records.first(), Some(&record));
return Poll::Ready(());
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
}
}
Poll::Pending
})
)
Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
}
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
/// A node joining a fully connected network via a single bootnode should be able to add itself as a
/// provider to the X closest nodes of the network where X is equal to the configured replication
/// factor.
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
#[test]
fn add_provider() {
fn prop(replication_factor: usize, keys: Vec<record::Key>) {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let replication_factor = NonZeroUsize::new(replication_factor % (K_VALUE.get() / 2) + 1).unwrap();
let num_total = replication_factor.get() * 2;
let mut config = KademliaConfig::default();
config.set_replication_factor(replication_factor);
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut swarms = {
let mut fully_connected_swarms = build_fully_connected_nodes_with_config(
num_total - 1,
config.clone(),
);
let mut single_swarm = build_node_with_config(config);
2020-04-21 19:54:30 +03:00
single_swarm.2.add_address(
Swarm::local_peer_id(&fully_connected_swarms[0].2),
fully_connected_swarms[0].1.clone(),
fully_connected_swarms[0].0.public(),
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
);
let mut swarms = vec![single_swarm];
swarms.append(&mut fully_connected_swarms);
// Drop addresses before returning.
2020-04-21 19:54:30 +03:00
swarms.into_iter().map(|(_, _addr, swarm)| swarm).collect::<Vec<_>>()
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
};
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let keys: HashSet<_> = keys.into_iter().take(num_total).collect();
// Each test run publishes all records twice.
let mut published = false;
let mut republished = false;
// The accumulated results for one round of publishing.
let mut results = Vec::new();
// Initiate the first round of publishing.
for k in &keys {
2020-04-21 19:54:30 +03:00
swarms[0].start_providing(k.clone());
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
block_on(
poll_fn(move |ctx| loop {
// Poll all swarms until they are "Pending".
2020-04-21 19:54:30 +03:00
for swarm in &mut swarms {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
loop {
match swarm.poll_next_unpin(ctx) {
Poll::Ready(Some(KademliaEvent::StartProvidingResult(res))) |
Poll::Ready(Some(KademliaEvent::RepublishProviderResult(res))) => {
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
match res {
Err(e) => panic!(e),
Ok(ok) => {
assert!(keys.contains(&ok.key));
results.push(ok.key);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
}
}
// Ignore any other event.
Poll::Ready(Some(_)) => (),
e @ Poll::Ready(_) => panic!("Unexpected return value: {:?}", e),
Poll::Pending => break,
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
}
}
if results.len() == keys.len() {
// All requests have been sent for one round of publishing.
published = true
}
if !published {
// Still waiting for all requests to be sent for one round
// of publishing.
return Poll::Pending
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
// A round of publishing is complete. Consume the results, checking that
// each key was published to the `replication_factor` closest peers.
while let Some(key) = results.pop() {
// Collect the nodes that have a provider record for `key`.
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let actual = swarms.iter().skip(1)
2020-04-21 19:54:30 +03:00
.filter_map(|swarm|
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
if swarm.store.providers(&key).len() == 1 {
Some(Swarm::local_peer_id(&swarm).clone())
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
} else {
None
})
.collect::<HashSet<_>>();
if actual.len() != replication_factor.get() {
// Still waiting for some nodes to process the request.
results.push(key);
return Poll::Pending
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
let mut expected = swarms.iter()
.skip(1)
.map(Swarm::local_peer_id)
.cloned()
.collect::<Vec<_>>();
let kbucket_key = kbucket::Key::new(key);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
expected.sort_by(|id1, id2|
kbucket::Key::new(id1.clone()).distance(&kbucket_key).cmp(
&kbucket::Key::new(id2.clone()).distance(&kbucket_key)));
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
let expected = expected
.into_iter()
.take(replication_factor.get())
.collect::<HashSet<_>>();
assert_eq!(actual, expected);
}
// One round of publishing is complete.
assert!(results.is_empty());
2020-04-21 19:54:30 +03:00
for swarm in &swarms {
src/query/peers/closest: Consider K_VALUE peers at initialization (#1536) * protocols/kad/query/peers/closest: Consider K_VALUE nodes at init By considering `K_VALUE` at `ClosestPeersIter` initialization, the initial peer set length is independent of `num_results` and thus of the `replication_factor`. * protocols/kad/src/behaviour/test: Enable building single nodes Introduces the `build_node` function to build a single not connected node. Along the way replace the notion of a `port_base` with returning the actual `Multiaddr` of the node. * protocols/kad/behaviour/test: Fix bootstrap test initialization When looking for the closest node to a key, Kademlia considers ALPHA_VALUE nodes to query at initialization. If `num_groups` is larger than ALPHA_VALUE the remaining locally known nodes will not be considered. Given that no other node is aware of them other than node 1, they would be lost entirely. To prevent the above restrict `num_groups` to be equal or smaller than ALPHA_VALUE. * protocols/kad/behaviour/test: Fix put_record and get_provider In the past, when trying to find the closest nodes to a key, Kademlia would consider `num_result` amount of nodes to query out of all the nodes it is aware of. Both the `put_record` and the `get_provider` tests initialized their swarms in the same way. The tests took the replication factor to use as an input. The number of results to get was equal to the replication factor. The amount of swarms to start was twice the replication factor. Nodes would be grouped in two groups a replication factor nodes. The first node would be aware of all of the nodes in the first group. The last node of the first group would be aware of all the nodes in the second group. By coincidence (I assume) these numbers played together very well. At initialization the first node would consider `num_results` amount of peers (see first paragraph). It would then contact each of them. As the first node is aware of the last node of the first group which in turn is aware of all nodes in the second group, the first node would eventually discover all nodes. Recently the amount of nodes Kademlia considers at initialization when looking for the nodes closest to a key was changed to only consider ALPHA nodes. With this in mind playing through the test setup above again would result in (1) `replication_factor - ALPHA` nodes being entirely lost as the first node would never consider them and (2) the first node probably never contacting the last node out of the first group and thus not discovering any nodes of the second group. To keep the multi hop discovery in place while not basing ones test setup on the lucky assumption of Kademlia considering replication factor amount of nodes at initialization, this patch alters the two tests: Build a fully connected set of nodes and one addition node (the first node). Connect the first node to a single node of the fully connected set (simulating a boot node). Continue as done previously. Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
2020-04-17 19:57:35 +02:00
assert_eq!(swarm.queries.size(), 0);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
if republished {
2020-04-21 19:54:30 +03:00
assert_eq!(swarms[0].store.provided().count(), keys.len());
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
for k in &keys {
2020-04-21 19:54:30 +03:00
swarms[0].stop_providing(&k);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
2020-04-21 19:54:30 +03:00
assert_eq!(swarms[0].store.provided().count(), 0);
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
// All records have been republished, thus the test is complete.
return Poll::Ready(());
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
}
// Initiate the second round of publishing by telling the
// periodic provider job to run asap.
2020-04-21 19:54:30 +03:00
swarms[0].add_provider_job.as_mut().unwrap().asap();
Kademlia: Somewhat complete the records implementation. (#1189) * Somewhat complete the implementation of Kademlia records. This commit relates to [libp2p-146] and [libp2p-1089]. * All records expire (by default, configurable). * Provider records are also stored in the RecordStore, and the RecordStore API extended. * Background jobs for periodic (re-)replication and (re-)publication of records. Regular (value-)records are subject to re-replication and re-publication as per standard Kademlia. Provider records are only subject to re-publication. * For standard Kademlia value lookups (quorum = 1), the record is cached at the closest peer to the key that did not return the value, as per standard Kademlia. * Expiration times of regular (value-)records is computed exponentially inversely proportional to the number of nodes between the local node and the closest node known to the key (beyond the k closest), as per standard Kademlia. The protobuf messages are extended with two fields: `ttl` and `publisher` in order to implement the different semantics of re-replication (by any of the k closest peers to the key, not affecting expiry) and re-publication (by the original publisher, resetting the expiry). This is not done yet in other libp2p Kademlia implementations, see e.g. [libp2p-go-323]. The new protobuf fields have been given somewhat unique identifiers to prevent future collision. Similarly, periodic re-publication of provider records does not seem to be done yet in other implementations, see e.g. [libp2p-js-98]. [libp2p-146]: https://github.com/libp2p/rust-libp2p/issues/146 [libp2p-1089]: https://github.com/libp2p/rust-libp2p/issues/1089 [libp2p-go-323]: https://github.com/libp2p/go-libp2p-kad-dht/issues/323 [libp2p-js-98]: https://github.com/libp2p/js-libp2p-kad-dht/issues/98 * Tweak kad-ipfs example. * Add missing files. * Ensure new delays are polled immediately. To ensure task notification, since `NotReady` is returned right after. * Fix ipfs-kad example and use wasm_timer. * Small cleanup. * Incorporate some feedback. * Adjustments after rebase. * Distinguish events further. In order for a user to easily distinguish the result of e.g. a `put_record` operation from the result of a later republication, different event constructors are used. Furthermore, for now, re-replication and "caching" of records (at the closest peer to the key that did not return a value during a successful lookup) do not yield events for now as they are less interesting. * Speed up tests for CI. * Small refinements and more documentation. * Guard a node against overriding records for which it considers itself to be the publisher. * Document the jobs module more extensively. * More inline docs around removal of "unreachable" addresses. * Remove wildcard re-exports. * Use NonZeroUsize for the constants. * Re-add method lost on merge. * Add missing 'pub'. * Further increase the timeout in the ipfs-kad example. * Readd log dependency to libp2p-kad. * Simplify RecordStore API slightly. * Some more commentary. * Change Addresses::remove to return Result<(),()>. Change the semantics of `Addresses::remove` so that the error case is unambiguous, instead of the success case. Use the `Result` for clearer semantics to that effect. * Add some documentation to .
2019-07-17 14:40:48 +02:00
published = false;
republished = true;
})
)
}
QuickCheck::new().tests(3).quickcheck(prop as fn(_,_))
}
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
/// User code should be able to start queries beyond the internal
/// query limit for background jobs. Originally this even produced an
/// arithmetic overflow, see https://github.com/libp2p/rust-libp2p/issues/1290.
#[test]
fn exceed_jobs_max_queries() {
2020-04-21 19:54:30 +03:00
let (_, _addr, mut swarm) = build_node();
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
let num = JOBS_MAX_QUERIES + 1;
for _ in 0 .. num {
2020-04-21 19:54:30 +03:00
swarm.bootstrap();
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
}
2020-04-21 19:54:30 +03:00
assert_eq!(swarm.queries.size(), num);
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
block_on(
poll_fn(move |ctx| {
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
for _ in 0 .. num {
// There are no other nodes, so the queries finish instantly.
2020-04-21 19:54:30 +03:00
if let Poll::Ready(Some(e)) = swarm.poll_next_unpin(ctx) {
if let KademliaEvent::BootstrapResult(r) = e {
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
assert!(r.is_ok(), "Unexpected error")
} else {
panic!("Unexpected event: {:?}", e)
}
} else {
panic!("Expected event")
}
}
Poll::Ready(())
})
)
Cherry-pick commits from master to stable-futures (#1296) * Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
2019-11-06 16:09:15 +01:00
}
#[test]
fn exp_decr_expiration_overflow() {
fn prop_no_panic(ttl: Duration, factor: u32) {
exp_decrease(ttl, factor);
}
// Right shifting a u64 by >63 results in a panic.
prop_no_panic(KademliaConfig::default().record_ttl.unwrap(), 64);
quickcheck(prop_no_panic as fn(_, _))
}