-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(peer-store): introduce libp2p-peer-store #5724
base: master
Are you sure you want to change the base?
Changes from 27 commits
1affefe
8d4930a
9cb59c3
fbc1344
2bcfa7f
6df6ee5
99a6bfd
5c7ba32
b6dcd59
cbb1906
6270259
cc91ab5
f9b040e
a9597da
0e6b280
fe14c42
92ac2fb
913ed1f
b8a7114
5f628fb
121e91b
47048ec
9da96ff
9945fd0
cb294c6
a9dc9aa
c94f636
a02f088
a909499
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
## 0.55.0(unreleased) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably will be addressed when solving the conflicts, but this doesn't need to be a minor, we can add the peer store as a patch release to the main |
||
|
||
- Introduce `libp2p-peer-store`. | ||
See [PR 5724](https://github.com/libp2p/rust-libp2p/pull/5724). | ||
|
||
## 0.54.2 | ||
|
||
- Add `with_connection_timeout` on `SwarmBuilder` to allow configuration of the connection_timeout parameter. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,7 @@ mdns = ["dep:libp2p-mdns"] | |
memory-connection-limits = ["dep:libp2p-memory-connection-limits"] | ||
metrics = ["dep:libp2p-metrics"] | ||
noise = ["dep:libp2p-noise"] | ||
# peer-store = ["dep:libp2p-peer-store"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to be uncommented right? |
||
ping = ["dep:libp2p-ping", "libp2p-metrics?/ping"] | ||
plaintext = ["dep:libp2p-plaintext"] | ||
pnet = ["dep:libp2p-pnet"] | ||
|
@@ -110,6 +111,7 @@ libp2p-identity = { workspace = true, features = ["rand"] } | |
libp2p-kad = { workspace = true, optional = true } | ||
libp2p-metrics = { workspace = true, optional = true } | ||
libp2p-noise = { workspace = true, optional = true } | ||
libp2p-peer-store = { workspace = true } | ||
libp2p-ping = { workspace = true, optional = true } | ||
libp2p-plaintext = { workspace = true, optional = true } | ||
libp2p-pnet = { workspace = true, optional = true } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## 0.1.0 | ||
|
||
- Introduce `libp2p-peer-store`. | ||
See [PR 5724](https://github.com/libp2p/rust-libp2p/pull/5724). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
name = "libp2p-peer-store" | ||
edition = "2021" | ||
drHuangMHT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
version = "0.1.0" | ||
authors = ["drHuangMHT <[email protected]>"] | ||
license = "MIT" | ||
repository = "https://github.com/libp2p/rust-libp2p" | ||
rust-version.workspace = true | ||
|
||
[dependencies] | ||
libp2p-core = { workspace = true } | ||
libp2p-swarm = { workspace = true } | ||
lru = "*" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to define proper versions of these dependencies |
||
futures-timer = "*" | ||
futures-util = "*" | ||
|
||
[dev-dependencies] | ||
libp2p-identity = { workspace = true, features = ["rand"] } | ||
|
||
[lints] | ||
workspace = true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
use std::{collections::VecDeque, task::Poll}; | ||
|
||
use libp2p_core::{Multiaddr, PeerId}; | ||
use libp2p_swarm::{dummy, NetworkBehaviour}; | ||
|
||
use crate::store::{AddressSource, Store}; | ||
|
||
/// Events generated by [`Behaviour`] and emitted back to the [`libp2p_swarm::Swarm`]. | ||
pub enum Event<S: Store> { | ||
/// The peer's record has been updated. | ||
/// Manually updating a record will always emit this event | ||
/// even if it provides no new information. | ||
RecordUpdated { | ||
peer: PeerId, | ||
}, | ||
Store(S::ToSwarm), | ||
} | ||
|
||
drHuangMHT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub struct Behaviour<S: Store> { | ||
store: S, | ||
/// Pending Events to be emitted back to the [`libp2p_swarm::Swarm`]. | ||
pending_events: VecDeque<Event<S>>, | ||
} | ||
|
||
drHuangMHT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
impl<'a, S> Behaviour<S> | ||
where | ||
S: Store + 'static, | ||
{ | ||
pub fn new(store: S) -> Self { | ||
Self { | ||
store, | ||
pending_events: VecDeque::new(), | ||
} | ||
} | ||
|
||
/// Try to get all observed address of the given peer. | ||
/// Returns `None` when the peer is not in the store. | ||
pub fn address_of_peer<'b>( | ||
&'a self, | ||
peer: &'b PeerId, | ||
) -> Option<impl Iterator<Item = &'a Multiaddr> + use<'a, 'b, S>> { | ||
self.store.addresses_of_peer(peer) | ||
} | ||
|
||
/// Manually update a record. | ||
/// This will always emit an `Event::RecordUpdated`. | ||
pub fn update_address(&mut self, peer: &PeerId, address: &Multiaddr) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. having this duplication where the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is for users who might want to update the cache from outside of the behavior. However if we only expect updates through swarm event, it can be removed. |
||
self.store | ||
.update_address(peer, address, AddressSource::Manual, false); | ||
self.pending_events | ||
.push_back(Event::RecordUpdated { peer: *peer }); | ||
} | ||
|
||
/// Should be called when other protocol emits a [`PeerRecord`](libp2p_core::PeerRecord). | ||
/// This will always emit an `Event::RecordUpdated`. | ||
pub fn on_signed_peer_record( | ||
&mut self, | ||
signed_record: &libp2p_core::PeerRecord, | ||
source: AddressSource, | ||
) { | ||
self.store | ||
.update_certified_address(signed_record, source, false); | ||
self.pending_events.push_back(Event::RecordUpdated { | ||
peer: signed_record.peer_id(), | ||
}); | ||
} | ||
|
||
/// Get a immutable reference to the internal store. | ||
pub fn store(&self) -> &S { | ||
&self.store | ||
} | ||
|
||
/// Get a mutable reference to the internal store. | ||
pub fn store_mut(&mut self) -> &mut S { | ||
&mut self.store | ||
} | ||
|
||
fn on_address_update( | ||
&mut self, | ||
peer: &PeerId, | ||
address: &Multiaddr, | ||
source: AddressSource, | ||
should_expire: bool, | ||
) { | ||
if self | ||
.store | ||
.update_address(peer, address, source, should_expire) | ||
{ | ||
self.pending_events | ||
.push_back(Event::RecordUpdated { peer: *peer }); | ||
} | ||
} | ||
fn handle_store_event(&mut self, event: super::store::Event) { | ||
use super::store::Event::*; | ||
match event { | ||
RecordUpdated(peer) => self.pending_events.push_back(Event::RecordUpdated { peer }), | ||
} | ||
} | ||
} | ||
|
||
impl<S> NetworkBehaviour for Behaviour<S> | ||
where | ||
S: Store + 'static, | ||
<S as Store>::ToSwarm: Send + Sync, | ||
{ | ||
type ConnectionHandler = dummy::ConnectionHandler; | ||
|
||
type ToSwarm = Event<S>; | ||
|
||
fn handle_established_inbound_connection( | ||
&mut self, | ||
_connection_id: libp2p_swarm::ConnectionId, | ||
peer: libp2p_core::PeerId, | ||
_local_addr: &libp2p_core::Multiaddr, | ||
remote_addr: &libp2p_core::Multiaddr, | ||
) -> Result<libp2p_swarm::THandler<Self>, libp2p_swarm::ConnectionDenied> { | ||
self.on_address_update(&peer, remote_addr, AddressSource::DirectConnection, false); | ||
Ok(dummy::ConnectionHandler) | ||
} | ||
|
||
fn handle_pending_outbound_connection( | ||
&mut self, | ||
_connection_id: libp2p_swarm::ConnectionId, | ||
maybe_peer: Option<PeerId>, | ||
_addresses: &[Multiaddr], | ||
_effective_role: libp2p_core::Endpoint, | ||
) -> Result<Vec<Multiaddr>, libp2p_swarm::ConnectionDenied> { | ||
if maybe_peer.is_none() { | ||
return Ok(Vec::new()); | ||
} | ||
let peer = maybe_peer.expect("already handled"); | ||
Ok(self | ||
.store | ||
.addresses_of_peer(&peer) | ||
.map(|i| i.cloned().collect()) | ||
.unwrap_or_default()) | ||
} | ||
|
||
fn handle_established_outbound_connection( | ||
&mut self, | ||
_connection_id: libp2p_swarm::ConnectionId, | ||
peer: libp2p_core::PeerId, | ||
addr: &libp2p_core::Multiaddr, | ||
_role_override: libp2p_core::Endpoint, | ||
_port_use: libp2p_core::transport::PortUse, | ||
) -> Result<libp2p_swarm::THandler<Self>, libp2p_swarm::ConnectionDenied> { | ||
self.on_address_update(&peer, addr, AddressSource::DirectConnection, false); | ||
Ok(dummy::ConnectionHandler) | ||
} | ||
|
||
fn on_swarm_event(&mut self, event: libp2p_swarm::FromSwarm) { | ||
if let Some(ev) = self.store.on_swarm_event(&event) { | ||
self.handle_store_event(ev); | ||
}; | ||
} | ||
|
||
fn on_connection_handler_event( | ||
&mut self, | ||
_peer_id: libp2p_core::PeerId, | ||
_connection_id: libp2p_swarm::ConnectionId, | ||
_event: libp2p_swarm::THandlerOutEvent<Self>, | ||
) { | ||
unreachable!("No event will be produced by a dummy handler.") | ||
} | ||
|
||
fn poll( | ||
&mut self, | ||
cx: &mut std::task::Context<'_>, | ||
) -> std::task::Poll<libp2p_swarm::ToSwarm<Self::ToSwarm, libp2p_swarm::THandlerInEvent<Self>>> | ||
{ | ||
if let Some(ev) = self.pending_events.pop_front() { | ||
return Poll::Ready(libp2p_swarm::ToSwarm::GenerateEvent(ev)); | ||
} | ||
if let Some(ev) = self.store.poll(cx) { | ||
self.pending_events.push_back(Event::Store(ev)); | ||
}; | ||
Poll::Pending | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
mod behaviour; | ||
pub mod memory_store; | ||
mod store; | ||
|
||
pub use behaviour::{Behaviour, Event}; | ||
pub use store::Store; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't need this white space right?