Skip to content
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(swarm): introduce ranked external addr registry #4689

Closed
wants to merge 1 commit into from

Conversation

mxinden
Copy link
Member

@mxinden mxinden commented Oct 19, 2023

Description

Ranked external address registry based on the previous https://github.com/libp2p/rust-libp2p/blob/v0.51/swarm/src/registry.rs pluggeable as a NetworkBehaviour. Allows confirming external addresses in a probabilistic manner.

Notes & open questions

See context and discussion in #4688.

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • A changelog entry has been made in the appropriate crates

Ranked external address registry based on the previous
https://github.com/libp2p/rust-libp2p/blob/v0.51/swarm/src/registry.rs pluggeable as a
`NetworkBehaviour`. Allows confirming external addresses in a probabilistic manner.
Comment on lines +341 to +413
impl NetworkBehaviour for Addresses {
type ConnectionHandler = crate::dummy::ConnectionHandler;

type ToSwarm = Void;

fn handle_established_inbound_connection(
&mut self,
_connection_id: crate::ConnectionId,
peer: libp2p_identity::PeerId,
local_addr: &Multiaddr,
remote_addr: &Multiaddr,
) -> Result<crate::THandler<Self>, crate::ConnectionDenied> {
Ok(crate::dummy::ConnectionHandler)
}

fn handle_established_outbound_connection(
&mut self,
_connection_id: crate::ConnectionId,
peer: libp2p_identity::PeerId,
addr: &Multiaddr,
role_override: libp2p_core::Endpoint,
) -> Result<crate::THandler<Self>, crate::ConnectionDenied> {
Ok(crate::dummy::ConnectionHandler)
}

fn on_swarm_event(&mut self, event: crate::FromSwarm<Self::ConnectionHandler>) {
match event {
crate::FromSwarm::ConnectionEstablished(_) => todo!(),
crate::FromSwarm::ConnectionClosed(_) => todo!(),
crate::FromSwarm::AddressChange(_) => todo!(),
crate::FromSwarm::DialFailure(_) => todo!(),
crate::FromSwarm::ListenFailure(_) => todo!(),
crate::FromSwarm::NewListener(_) => todo!(),
crate::FromSwarm::NewListenAddr(_) => todo!(),
crate::FromSwarm::ExpiredListenAddr(_) => todo!(),
crate::FromSwarm::ListenerError(_) => todo!(),
crate::FromSwarm::ListenerClosed(_) => todo!(),
crate::FromSwarm::NewExternalAddrCandidate(NewExternalAddrCandidate { addr }) => {
match self.add(addr.clone(), AddressScore::Finite(1)) {
AddAddressResult::Inserted { expired } => {
todo!("emit ToSwarm::NewExternalAddr(addr) and ToSwarm::ExternalAddrExpired(expired)")
}
AddAddressResult::Updated { expired } => {
todo!("emit ToSwarm::ExternalAddrExpired(expired)")
}
};
}
crate::FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { addr }) => {
self.add(addr.clone(), AddressScore::Infinite);
}
crate::FromSwarm::ExternalAddrExpired(ExternalAddrExpired { addr }) => {
self.remove(addr);
}
}
}

fn on_connection_handler_event(
&mut self,
_peer_id: libp2p_identity::PeerId,
_connection_id: crate::ConnectionId,
event: crate::THandlerOutEvent<Self>,
) {
void::unreachable(event)
}

fn poll(
&mut self,
_cx: &mut std::task::Context<'_>,
_params: &mut impl crate::PollParameters,
) -> std::task::Poll<crate::ToSwarm<Self::ToSwarm, crate::THandlerInEvent<Self>>> {
Poll::Pending
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the only addition to the v0.51 version, namely the NetworkBehaviour implementation that would allow one to simply plug this into ones NetworkBehaviour tree.

Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to add something like this although I'd like to see the following changes:

  • Move it to a dedicated crate under misc/.
  • Don't call it registry but something that communicates the probabilistic nature of these external addresses.
  • Introduce a threshold of 2 for when we promote a candidate to an external address. That should effectively never promote ephemeral ports as external addresses.

@thomaseizinger
Copy link
Contributor

  • Move it to a dedicated crate under misc/.

Alternatively, we could also re-add such functionality back into Swarm but that would go against the current design philosophy of moving this kind of functionality into plugins.

@mxinden
Copy link
Member Author

mxinden commented Oct 20, 2023

Introduce a threshold of 2 for when we promote a candidate to an external address. That should effectively never promote ephemeral ports as external addresses.

I had the same thought. Problem though: libp2p-identify reports an observed address on each identify exchange as a new candidate. Two identify exchanges on the same connection could thus lead to an address being confirmed, even though the connection might be on an ephemeral port.

@thomaseizinger
Copy link
Contributor

Introduce a threshold of 2 for when we promote a candidate to an external address. That should effectively never promote ephemeral ports as external addresses.

I had the same thought. Problem though: libp2p-identify reports an observed address on each identify exchange as a new candidate. Two identify exchanges on the same connection could thus lead to an address being confirmed, even though the connection might be on an ephemeral port.

We can fix that right? We can remember, which ones we already reported and don't report them again. That might actually be more correct because the API says NewExternalAddrCandidate.

@thomaseizinger
Copy link
Contributor

Introduce a threshold of 2 for when we promote a candidate to an external address. That should effectively never promote ephemeral ports as external addresses.

I had the same thought. Problem though: libp2p-identify reports an observed address on each identify exchange as a new candidate. Two identify exchanges on the same connection could thus lead to an address being confirmed, even though the connection might be on an ephemeral port.

We can fix that right? We can remember, which ones we already reported and don't report them again. That might actually be more correct because the API says NewExternalAddrCandidate.

In theory, a connection could roam and change its address. If we want to ignore that for now, we could also go with a "Only report once" behaviour.

@thomaseizinger
Copy link
Contributor

Another idea:

We make libp2p-identify smarter: Instead of naively reporting each observed address, we only emit a candidate once at least X (default 2?) nodes reported us the same address. We might have to make it configurable for tests but this could be a good fix until we have the new PortUse information available, at which point we can probably just rely on that.

@thomaseizinger
Copy link
Contributor

Introduce a threshold of 2 for when we promote a candidate to an external address. That should effectively never promote ephemeral ports as external addresses.

I had the same thought. Problem though: libp2p-identify reports an observed address on each identify exchange as a new candidate. Two identify exchanges on the same connection could thus lead to an address being confirmed, even though the connection might be on an ephemeral port.

We can fix that right? We can remember, which ones we already reported and don't report them again. That might actually be more correct because the API says NewExternalAddrCandidate.

I implemented this here: #4721

@thomaseizinger
Copy link
Contributor

Closing in favor of #4721.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants