-
Notifications
You must be signed in to change notification settings - Fork 446
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
fix!: refactor connection manager to use a prioritised queue #1678
Conversation
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.
Partial review
// these should now be ranges expressed as MultiaddrFilters | ||
allow: [ | ||
'/ip4/0.0.0.0/tcp/123' | ||
], | ||
|
||
// these should now be ranges expressed as MultiaddrFilters | ||
deny: [ | ||
'/ip4/0.0.0.0/tcp/123' | ||
] |
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.
Can we get a "allow peer" that allows any appropriate transports given a specific peerId?
I was trying to do that the other day in kubo and realized i needed a full multiaddr. I was trying to grant full-access to/from my helia node and couldn't figure out how to do it within an hour or so and i gave up.
It would be great to be able to do that in js-libp2p
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.
I'm a little confused, access is allowed by default, it's only disallowed if a configured connection gater denys it or you're at maxConnections
already.
The allow
list above enables specific networks to breach connection limits - a DoS mitigation for when your node is being eclipsed.
It's almost certainly not the solution to your problem - maybe you can open an issue on the helia repo with a repro case?
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.
sure. I will re-open if I run into it.. essentially what I was trying to do was prefer my local node to others, and to allow connections to that one no matter what. it sounds like that may not be necessary
// a low value allows user-initiated dials to take priority over | ||
// auto dials | ||
autoDialPriority: 0, |
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.
Nice
// this was previously named `maxAddrsToDial` | ||
maxPeerAddrsToDial: 20, |
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.
PerConnection attempt? Or total(then we banlist the peer as bad??)
Might be good to call out which one and how in jsdoc, or in the name if possible.
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.
Did you check the jsdoc for this config option? If it's not clear could you suggest an edit?
doc/migrations/v0.43-v0.44.md
Outdated
// this was previously named `maxDialsPerPeer` | ||
maxParallelDialsPerPeer: 20, |
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.
Just so i understand fully, this setting changes whether we can attempt to dial 2 or 20 multiaddrs at once when attempting to connect to a specific peer, correct?
Would 'maxParallelMultiAddrDialsPerPeer' be a more explicit name? Is there a way we can get that explicitness without the verbosity?
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 only dial multiaddrs so maybe having MultiAddr
in the name is redundant?
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.
But yes, a setting of 2
with a peer that has 10
addresses means we'll dial all 10 addresses but only ever 2 at once. This stops a peer with a lot of spam addresses blocking the dial queue.
doc/migrations/v0.43-v0.44.md
Outdated
// these should now be ranges expressed as MultiaddrFilters | ||
allow: [ | ||
new MultiaddrFilter('/ip4/192.168.1.1/ipcidr/32') | ||
], | ||
|
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.
As above, can i create a multiaddrFilter consisting only of '/p2p/peerId' ?
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.
No, the allow/deny lists are for allowing/denying classes of network to make connections - this happens before the peer id exchange so we don't know who the remote peer is at that point.
It's a DoS mitigation strategy to always allow connections from networks you know, control or trust, or disallow connections from networks that are attacking you.
To deny specific peers you can implement a connection gater.
denyDialMultiaddr: (multiaddr) => { | ||
if (multiaddr.getPeerId() != null) { | ||
// there is a peer id present in the multiaddr | ||
} |
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.
👍
src/connection-manager/auto-dial.ts
Outdated
* The minimum number of connections below which libp2p will start to dial | ||
* peers from the peer book. (default: 0) | ||
*/ | ||
minConnections?: number |
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.
MinConnections: 0 is the same as saying, I'm allowed to have zero connections, don't autoDial, correct?
Might be useful to call out that setting this to zero disables it
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.
Turns out that default was wrong 🤭 - would much rather generate that info but not sure how.
I've updated the jsdoc for this setting - if it's still not clear could you suggest an edit?
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.
js-libp2p/src/connection-manager/index.ts
Lines 39 to 44 in 4078082
/** | |
* The minimum number of connections below which libp2p will start to dial peers | |
* from the peer book. Setting this to 0 effectively disables this behaviour. | |
* (default: 50) | |
*/ | |
minConnections?: number |
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.
Great work on this @achingbrain will definitely improve with connection management overall. I made some comments and suggestions.
I think these are a lot of changes though and perhaps we should split this into some smaller PRs to make reviewing a bit easier and the changes more manageable. I would suggest separate PRs for:
- Use standard IP cidr format for allow/deny lists #1510
- bug: heliaInstance.libp2p.addEventListener('peer:discovery', cb) calls cb twice for same peer #1630
denyDialMultiaddr
method now only takes amultiaddr
and also the other interfaces updates required with it.
…ling Refactors the connection manager. 1. Internally it uses a queue to control concurrency instead of dial tokens 2. A second queue is used for each peer to prevent inividual peers from swamping the dial queue 3. The auto dialler now checks the minimum connection limit when peers disconnect instead of using a timer 4. Auto dialled peers are sorted based on tag value so valuable peers should be re-dialled first 5. Auto dialled peers are dialled in parallel to prevent a slow peer locking up the auto-dial queue 6. allow/deny lists are now `MultiaddrFilter`s 7. A `getDialQueue` method has been added to libp2p to allow inspection of the dial queue though it needs exposing in the interface 8. The connection gater `denyDialMultiaddr` method now only takes a multiaddr BREAKING CHANGE: some connection manager options have changed - please see the upgrade guide for full details
Co-authored-by: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com>
dbca29e
to
3d92f93
Compare
I've removed the attempt at resolving the double-peer discovery bug - I think it needs a bit more thought, basically the logic to determine whether to emit the event is complicated and will be vastly simplified by having an atomic peer store. The auto dial interval has also returned - this is because I found an edge case where we could still end up with no peers if all auto-dials failed - if network connection is lost, for example. I've reverted the |
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.
LGTM
All good. |
Refactors the connection manager.
maxParallelDials
)maxParallelDialsPerPeer
)getDialQueue
method has been added to libp2p to allow inspection of the dial queue though it needs exposing in the interfacedenyDialMultiaddr
method now only takes a multiaddrpeer:connect
events not before - fixes Should not emit peer:connect with a closed connection #1565BREAKING CHANGE: some connection manager options have changed - please see the upgrade guide for full details