Feat: add Manual type to ConnectionKinds#866
Conversation
Manual type to ConnectionKinds
| } | ||
|
|
||
| #[derive(Debug, PartialEq, Clone, Copy)] | ||
| /// The kind of connection we see this peer as. |
There was a problem hiding this comment.
Add a link to the Core counterpart, useful
52d1361 to
e0027b9
Compare
e0027b9 to
27b5f92
Compare
|
Fixed a lint error |
| /// A feeler connection is a short-lived connection used to check whether this peer is alive. | ||
| /// | ||
| /// After handshake, we ask for addresses and when we receive an answer we just disconnect, | ||
| /// marking this peer as alive in our address manager |
There was a problem hiding this comment.
| /// marking this peer as alive in our address manager | |
| /// marking this peer as alive in our address manager. |
There was a problem hiding this comment.
We don't apply punctuation very evenly. Perhaps we should add this to our coding style, and update all docs as we go (same we are doing with structs)
There was a problem hiding this comment.
For single-line comments it is fine to not punctuate IMO, but for these longer docstrings better to do it
| /// marking this peer as alive in our address manager | ||
| Feeler, | ||
|
|
||
| /// A regular peer, used to send requests to and learn about transactions and blocks |
There was a problem hiding this comment.
| /// A regular peer, used to send requests to and learn about transactions and blocks | |
| /// A regular peer, used to send requests to and learn about transactions and blocks. |
| /// A regular peer, used to send requests to and learn about transactions and blocks | ||
| Regular(ServiceFlags), | ||
|
|
||
| /// An extra peer specially created if our tip haven't moved for too long |
There was a problem hiding this comment.
| /// An extra peer specially created if our tip haven't moved for too long | |
| /// An extra peer specially created if our tip hasn't moved for too long. |
| /// If more than [`NodeContext::ASSUME_STALE`] seconds has passed since the | ||
| /// processed block. We use this to make sure we are not in a partitioned subnet, | ||
| /// unable to learn about new blocks |
There was a problem hiding this comment.
| /// If more than [`NodeContext::ASSUME_STALE`] seconds has passed since the | |
| /// processed block. We use this to make sure we are not in a partitioned subnet, | |
| /// unable to learn about new blocks | |
| /// If more than [`NodeContext::ASSUME_STALE`] seconds have passed since the | |
| /// last processed block, we use this to make sure we are not in a partitioned subnet, | |
| /// unable to learn about new blocks. |
27b5f92 to
b7a39cc
Compare
|
Pushed b7a39cc applying minor docs fixes by @JoseSK999 |
| pub(crate) fn create_connection(&mut self, kind: ConnectionKind) -> Result<(), WireError> { | ||
| // Connection with fixed peers should be marked as `manual`, rather than `regular` | ||
| let connection_kind = match (self.fixed_peer.as_ref(), kind) { | ||
| (Some(_), ConnectionKind::Regular(_)) => ConnectionKind::Manual, | ||
| _ => kind, | ||
| }; |
There was a problem hiding this comment.
What if we change the signature to mut kind: ConnectionKind, and mutate it to Manual if needed. To avoid having two kind variables within scope.
I think this is nice, so you can reuse the is_fixed variable at L120:
pub(crate) fn create_connection(&mut self, mut kind: ConnectionKind) -> Result<(), WireError> {
let is_fixed = self.fixed_peer.is_some();
// Connection with fixed peers should be marked as `manual`, rather than `regular`
if is_fixed && matches!(kind, ConnectionKind::Regular(_)) {
kind = ConnectionKind::Manual;
}b7a39cc to
2821fd5
Compare
There was a problem hiding this comment.
Wait, the is_fixed one? I think it's still relevant, we need to allow fallback for manual peers. We would also need to change peer.rs to always fallback on manual peers
There was a problem hiding this comment.
You have that variable defined twice after applying my suggestion, I mean. You can remove this one.
| match kind { | ||
| ConnectionKind::Feeler => self.last_feeler = Instant::now(), | ||
| ConnectionKind::Regular(_) => self.last_connection = Instant::now(), | ||
| // Note: Crating a manual peer intentionally don't prevent us from checking our peers |
There was a problem hiding this comment.
| // Note: Crating a manual peer intentionally don't prevent us from checking our peers | |
| // Note: creating a manual peer intentionally doesn't prevent us from checking our peers |
But I don't understand the point you are trying to make in this comment
There was a problem hiding this comment.
We still call check_connections in the same moment we would, regardless of already having a new connection
There was a problem hiding this comment.
Ahh, perhaps a rephrase to say manual peers don’t affect the check connection waiting time
There was a problem hiding this comment.
Rephrased to mention the timer
| // Connections that will continue open for as long as we are running (and the other | ||
| // peer don't die) |
There was a problem hiding this comment.
| // Connections that will continue open for as long as we are running (and the other | |
| // peer don't die) | |
| // Connections expected to remain open if the peer doesn't die |
| || matches!(p.kind, ConnectionKind::Manual); | ||
| p.state == PeerStatus::Ready && long_lived_connection |
| || matches!(p.kind, ConnectionKind::Manual); | ||
| if long_lived && p.state == PeerStatus::Ready { |
| @@ -137,12 +138,11 @@ | |||
| // peer and create a utreexo and CBS connection | |||
| if !self.has_utreexo_peers() { | |||
| if self.peer_ids.len() == 10 { | |||
There was a problem hiding this comment.
Maybe we can do this now that you touch it:
| if self.peer_ids.len() == 10 { | |
| if self.peer_ids.len() >= RunningNode::MAX_OUTGOING_PEERS { |
There was a problem hiding this comment.
Or should we use connected_peers to not count feelers?
| @@ -153,12 +153,11 @@ | |||
| return Ok(()); | |||
| } | |||
| if self.peer_ids.len() == 10 { | |||
There was a problem hiding this comment.
and here
| if self.peer_ids.len() == 10 { | |
| if self.peer_ids.len() >= RunningNode::MAX_OUTGOING_PEERS { |
| info.kind = ConnectionKind::Regular(peer_info.services); | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
Why were we updating peer info here 🤨
There was a problem hiding this comment.
I think that was actually a bug 👀
If a feeler connection sent us headers, they would be promoted to Regular
|
|
||
| // disconnect the peer with the lowest score | ||
| if let Some(peer) = peer_to_disconnect { | ||
| self.send_to_peer(peer, NodeRequest::Shutdown)?; |
There was a problem hiding this comment.
Just a comment:
I saw a lot of these cases where the connection kind where checked to see if a peer should be disconnected, would be good to have unified methods for the each ConnectionKind exception.
There was a problem hiding this comment.
I've added some helper methods in LocalPeerView and used them. I think we can't trivially remove anything else
2459abc to
a4ba5f6
Compare
|
Pushed
|
| match kind { | ||
| ConnectionKind::Feeler => self.last_feeler = Instant::now(), | ||
| ConnectionKind::Regular(_) => self.last_connection = Instant::now(), | ||
| // Note: Creating a manual peer intentionally doesn't affect the `last_connection |
There was a problem hiding this comment.
| // Note: Creating a manual peer intentionally doesn't affect the `last_connection | |
| // Note: Creating a manual peer intentionally doesn't affect the `last_connection` |
| pub(crate) const fn is_long_lived(&self) -> bool { | ||
| matches!(self.kind, ConnectionKind::Regular(_)) | ||
| || matches!(self.kind, ConnectionKind::Manual) | ||
| } |
There was a problem hiding this comment.
Tiny nit
| pub(crate) const fn is_long_lived(&self) -> bool { | |
| matches!(self.kind, ConnectionKind::Regular(_)) | |
| || matches!(self.kind, ConnectionKind::Manual) | |
| } | |
| pub(crate) const fn is_long_lived(&self) -> bool { | |
| self.is_regular_peer() || self.is_manual_peer() | |
| } |
There was a problem hiding this comment.
Since you are at it too
| let total_peers = self.connected_peers(); |
a4ba5f6 to
525cc0c
Compare
|
Pushed 525cc0c fixing nits by @JoseSK999 |
|
Note there's a case where we would disconnect the manual peer, which is when it sends an invalid block, and we call But probably we want to call EDIT: I think we can just add a return here to fix it and then in a followup merge a bit these two functions. |
| if let Some(peer) = self.peers.get(&peer) { | ||
| let ban_state = AddressState::Banned(T::BAN_TIME); |
There was a problem hiding this comment.
Add early return to fix it
if let Some(peer) = self.peers.get(&peer) {
// Manual connections are exempt from being punished
if peer.is_manual_peer() {
return Ok(());
}
let ban_state = AddressState::Banned(T::BAN_TIME);525cc0c to
e0d9a85
Compare
Oh shoot, right! Pushed the temporary fix, ACK on refactoring those functions. |
All peers that are added by the user — those added with the RPC
`addnode` or the CLI option `--connect`, should have kind `Manual`,
rather than `Regular`. This excempts them from:
- Max peers quota — if we already have 10 peers and the user tries
to addnode another one, we will now have 11 peers
- They whitelisted and shouldn't be banned by misbehaving
- They don't need to have any required service
This commit adds this new variant, and makes sure we are following
the above rules.
Manual connections are whitelisted and should not be banned, even if they misbehave. This commit makes sure we are not doing so. I've removed all the times we just disconnect a misbehaving peer with a call to `increase_banscore` with the maximum `banscore` as the increase amount (so they will be banned right away)
e0d9a85 to
6de9fa1
Compare
|
Sorry, @JoseSK999. But I've fixed that annoying but where we would get nine peers and get stuck. |
|
ACK 6de9fa1 |
|
Next on: batch connections 👨🏻🍳 |
Description and Notes
All peers that are added by the user — those added with the RPC
addnodeor the CLI option--connect, should have kindManual,rather than
Regular. This exempts them from:to addnode another one, we will now have 11 peers
This commit adds this new variant, and makes sure we are following
the above rules.
This is a small subset of #636, and will be useful for getting #865 unstuck (potentially can help with some edge cases as mentioned in #852 (comment))