fix: another bundle of small fixes for how we select peers#904
fix: another bundle of small fixes for how we select peers#904Davidson-Souza merged 9 commits intogetfloresta:masterfrom
Conversation
d922a3e to
77fd684
Compare
| "Tried": 0 | ||
| }, | ||
| "services": 1037, | ||
| "services": 1033, |
There was a problem hiding this comment.
Currently we can't connect to these, if these don't support P2Pv2. Just noting this.
There was a problem hiding this comment.
We need to test all those peers to check if they are still alive. A little offtopic for this PR tho
|
In cf61fbb you say "don't try to create a normal connection |
| // Don't allow our node to have more than T::MAX_OUTGOING_PEERS, unless this is a | ||
| // manual peer, those can exceed our quota. | ||
|
|
There was a problem hiding this comment.
Nit: remove these lines, you already added one updated comment below
|
|
||
| // We allow utreexo and manual peers to bypass our connection limis | ||
| let is_utreexo_peer = | ||
| version.kind == ConnectionKind::Regular(service_flags::UTREEXO.into()); |
There was a problem hiding this comment.
I think this is incorrect since you can have other service bits, so this will not be equal even if this is a bridge node
|
|
||
| let idx = rand::random::<usize>() % peers.len(); | ||
| let utreexo_peer = peers.get(idx)?; | ||
| let utreexo_peer = *peers.get(idx)?; |
There was a problem hiding this comment.
Nit, this shouldn't assume the peer is utreexo, we can use other service bits
77fd684 to
09dc21c
Compare
| fn get_address_by_service(&self, service: ServiceFlags) -> Option<(usize, LocalAddress)> { | ||
| let peers = self.good_peers_by_service.get(&service)?; | ||
| let peers: Vec<_> = self | ||
| .good_peers_by_service | ||
| .get(&service)? | ||
| .iter() | ||
| .filter_map(|address| { | ||
| let local_address = self.addresses.get(address)?; | ||
| if local_address.state == AddressState::Connected { | ||
| return None; | ||
| } | ||
|
|
||
| Some(local_address.id) | ||
| }) | ||
| .collect(); | ||
|
|
||
| if peers.is_empty() { | ||
| return None; | ||
| } | ||
|
|
||
| let idx = rand::random::<usize>() % peers.len(); | ||
| let utreexo_peer = peers.get(idx)?; | ||
| let address_id = *peers.get(idx)?; | ||
|
|
||
| Some((*utreexo_peer, self.addresses.get(utreexo_peer)?.to_owned())) | ||
| Some((peer_id, self.addresses.get(&address_id)?.to_owned())) | ||
| } |
| pub fn update_set_service_flag(&mut self, idx: usize, flags: ServiceFlags) -> &mut Self { | ||
| // if this peer turns out to not have the minimum required services, we remove it | ||
| if !flags.has(ServiceFlags::NETWORK) || !flags.has(ServiceFlags::WITNESS) { | ||
| if !flags.has(ServiceFlags::NETWORK_LIMITED) || !flags.has(ServiceFlags::WITNESS) { |
There was a problem hiding this comment.
Does NETWORK also imply NETWORK_LIMITED? If not, NETWORK should remain there and NETWORK_LIMITED should be added.
There was a problem hiding this comment.
If we require NETWORK we will drop all pruned nodes from addr_man
| let signet_address = | ||
| load_addresses_from_json("./src/p2p_wire/seeds/signet_seeds.json").unwrap(); |
| ServiceFlags::NETWORK | ServiceFlags::WITNESS | service_flags::UTREEXO_ARCHIVE.into() | ||
| } | ||
|
|
||
| const TRY_NEW_CONNECTION: u64 = 30; // 30 seconds |
There was a problem hiding this comment.
On 9be7162 you just removed TRY_NEW_CONNECTION, but where is the new 10 second value coming from?
There was a problem hiding this comment.
In node_context.rs it is set to 10s by default
| self.inflight | ||
| .insert(InflightRequests::GetAddresses, (peer, Instant::now())); | ||
|
|
||
| let good_peers_count = self.connected_peers(); |
There was a problem hiding this comment.
self.connected_peers() should return the actual peers, not the count.
There was a problem hiding this comment.
Or be renamed to reflect that it returns a count, we use it in several places already. Fells a bit off-topic for this PR tho
09dc21c to
ed858fd
Compare
|
Trying this tomorrow morning🫡 |
ed858fd to
9e69e92
Compare
|
I forgot to push some fixes suggested by @luisschwab |
9e69e92 to
92f3c38
Compare
| fn get_address_by_service(&self, service: ServiceFlags) -> Option<(usize, LocalAddress)> { | ||
| let peers = self.good_peers_by_service.get(&service)?; | ||
| let peers: Vec<_> = self | ||
| .good_peers_by_service | ||
| .get(&service)? | ||
| .iter() | ||
| .filter_map(|address| { | ||
| let local_address = self.addresses.get(address)?; | ||
| if local_address.state == AddressState::Connected { | ||
| return None; | ||
| } | ||
|
|
||
| Some(local_address.id) | ||
| }) | ||
| .collect(); | ||
|
|
||
| if peers.is_empty() { | ||
| return None; | ||
| } | ||
|
|
||
| let idx = rand::random::<usize>() % peers.len(); | ||
| let utreexo_peer = peers.get(idx)?; | ||
| let address_id = *peers.get(idx)?; | ||
|
|
||
| Some((*utreexo_peer, self.addresses.get(utreexo_peer)?.to_owned())) | ||
| Some((address_id, self.addresses.get(&address_id)?.to_owned())) | ||
| } |
There was a problem hiding this comment.
Compact version, avoiding calling self.addresses.get twice
fn get_address_by_service(&self, service: ServiceFlags) -> Option<(usize, LocalAddress)> {
let candidates = self.good_peers_by_service.get(&service)?;
candidates
.iter()
.filter_map(|id| {
let addr = self.addresses.get(id)?;
(addr.state != AddressState::Connected).then_some((id, addr))
})
.choose(&mut rand::thread_rng())
.map(|(id, addr)| (*id, addr.to_owned()))
}| self.peers.entry(peer).and_modify(|p| { | ||
| p.kind = ConnectionKind::Feeler; | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| if version.kind == ConnectionKind::Feeler { |
There was a problem hiding this comment.
I think you didn't actually fix it, we modify the kind to be feeler on self.peers, but then we check against the Version message which won't be feeler.
Also what if this is an extra connection, we shouldn't convert it into a feeler even if we have excess peers.
…vice Currently, `get_address_by_service` will return addresses that we are already connected. Since the address selection logic first calls this function, and only if it returns `None`, tries a random (not known-to-be-good peer), we end up only getting connected peers in the main loop of `get_address_to_connect`. In turn, since we don't return connected addresses from that function, we return a large amount of `None`'s if we try to get address for a poorly populated service. This commit now filters out connected peers, so we don't even consider them. If there's no peers besides the connected ones, then we fallback to trying the "not good" addresses.
We previously required NETWORK, which excludes pruned nodes. `push_addresses` also requires NETWORK_LIMITED.
This test adds fixed addresses to the address manager and checks whether they actually have been added.
This commit reduces the interval between connection attempts to 10 secods (the default for NodeContext).
92f3c38 to
a6c831d
Compare
|
Pushed a6c831d:
|
| } | ||
|
|
||
| #[test] | ||
| fn test_adding_fixed_peer() { |
There was a problem hiding this comment.
I noticed this supersedes test_add_fixed_addresses, right? We should just add here the not empty check to keep this strictly a super-set of checks
There was a problem hiding this comment.
Not really, test_add_fixed_addresses is using AddressMan::add_fixed_addresses, this new test does it manually to have access to the raw data
|
|
||
| let good_peers_count = self.connected_peers(); | ||
| if good_peers_count > T::MAX_OUTGOING_PEERS { | ||
| // We allow utreexo and manual peers to bypass our connection limis |
There was a problem hiding this comment.
| // We allow utreexo and manual peers to bypass our connection limis | |
| // We allow utreexo and manual peers to bypass our connection limits |
| let is_utreexo_peer = matches!(version.kind, ConnectionKind::Regular(services) if services.has(service_flags::UTREEXO.into())); | ||
| let is_manual_peer = version.kind == ConnectionKind::Manual; | ||
|
|
||
| if !(is_utreexo_peer || is_manual_peer) { |
There was a problem hiding this comment.
My comment on the extra peer is unresolved. I think we will convert any extra peer into feeler here, we should exclude those as well.
Before this commit, we would turn peers that exceeds our maximum peers count into a Feeler connection. However, we didn't update the services and state for that address, making our node believe that was a `Failed` connection, rather than a `Tried` one. This commit fixes this by removing the early return and move that code to before the logic that handles feeler connections.
… peers This will make sure we can create more than one utreexo connection, currently if we have only one utreexo peer, we won't use hardcoded addresses, and potentially have only one for the whole IBD, slowing things down.
a6c831d to
857a80b
Compare
|
Pushed 857a80b:
|
Description and Notes
This PR bundles a couple of small changes intended to make our node more effective at finding Utreexo peers. See each commit message for more details about what they are changing and why.
Changelog: