-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Rework addnode behaviour #8113
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
Rework addnode behaviour #8113
Conversation
2307f4a
to
b395c90
Compare
This is a more invasive change than #8097, but concept ACK.
Looks like we don't have any RPC tests for |
Basic testing for getaddednodeinfo/addnode should certainly be added, but the specific case being changed here would be very hard to test without beind able to mock out name resolving... |
Yes, agreed. Maybe that's a future possibility after the net refactor. IMO the most important privacy invariant for DNS changes is that we don't ever do DNS queries when In any case that's a tangent. I think #8097 was nice in that it was only a local change to an (apparently rarely used) RPC call. This involves some regression risk for code outside that as well. On the other hand this is a more thorough solution, and at least one person (@TheBlueMatt) cares about the functionality it seems better to do that. @theuni can you take a look? |
Concept ACK. Thanks, @sipa! Will review in detail. |
This looks great. A few notes:
I'll work on some real testing. Yes, I have planned (for later, not initially) for functionality to spoof resolved results for easier dns testing as part of the net refactor. For now, I'll just spoof system-wide. |
I don't think that matters. If fDisconnect is set, it tends to be processed quickly.
Only the random order changed. The old code would consecutively try all IPs from all addnodes, but with an inner loop over the -addnode arguments (with 0.5s delay), and an outer loop (with 120s delay) over the multiple lookup results.
Sounds like a good idea, but that's independent of this PR, right? |
Yikes, yet another misreading of this code on my part. I misunderstood the connection logic post-resolve. So nevermind the ConnectSocketByName comment. Yes, the condvar can come later. |
@sipa This needs theuni@c22dc8e in order for 'getaddednodeinfo' to properly report the connected ip. Tested (via RPC, at least) ACK with the fix above. The rest looks sane. Though I suspect @TheBlueMatt will object to the behavioral change here. IMO it's more sane in that it lines up with my expectations of how this would work, but it breaks the "addnode a dns entry and it will quickly detect a change and create a new connection" persistence model. I'd like to point out that this logic is also much easier to re-implement in the refactored code, as the internal connection handler doesn't need to keep up with application state. Instead, it will just retry a dns connection any time the current one disconnects. |
CNode* pnode = FindNode((CService)addrConnect); | ||
if (pnode) | ||
{ | ||
pnode->AddRef(); |
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.
What Release()s this?
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 just copied the behaviour of the "// Look for existing connection" logic above. I assume that ConnectNode always returns something with an incremented refcount that the caller is supposed to deal with.
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.
Ok. I was already suspicious of the current refcounting logic, but copying the current behavior makes sense. I'll look into that separately.
Rebased, and incorporated @theuni's fix to the RPC output. |
@TheBlueMatt can you give your OK on whether this still supports your use case? |
* Use CNode::addeName to track whether a connection to a name is already open * A new connection to a previously-connected by-name addednode is only opened when the previous one closes (even if the name starts resolving to something else) * At most one connection is opened per addednode (even if the name resolves to multiple) * Unify the code between ThreadOpenAddedNodeConnections and getaddednodeinfo * Information about open connections is always returned, and the dns argument becomes a dummy * An IP address and inbound/outbound is only reported for the (at most 1) open connection
Rebased. |
Nit: let's make the |
I don't have any luck using it to connect to hostnames. E.g. when trying to add a testnet seed (which I know for fact is returing valid addresses most of the time):
|
Got it to work now, after setting up a fake hostname instead of using a seed, and prodding it a bit:
|
I'm really not a huge fan of not following DNS changes until after the previous connection dies, but it does not effect me, personally. In any case, all of the addnode logic needs to be better documented somewhere. |
utACK. I think the new behavior is more useful and explicable. |
1a5a4e6 Randomize name lookup result in ConnectSocketByName (Pieter Wuille) f9f5cfc Prevent duplicate connections where one is by name and another by ip (Pieter Wuille) 1111b80 Rework addnode behaviour (Pieter Wuille)
Not sure if related but this was reported on IRC by @jonasschnelli:
|
5e79989 Randomize name lookup result in ConnectSocketByName (Pieter Wuille) cdc1d9f Rework addnode behaviour (Pieter Wuille) Pull request description: Partial backport of bitcoin#8113 as part of #1374. Original Description: > * Maintains consistency between ThreadOpenAddedNodeConnections and getaddednodeinfo, without any DNS resolving from RPC. > * Deals with the use case of added names whose IP mapping changes over time (switching over to the new IP only when the connection to the old one closes, though). > * Gets rid of the fDns argument to getaddednodeinfo (turning it into a dummy) > * Simplifies the code significantly by introducing a shared GetAddedNodeInfo in net.cpp. > * The existing addnode logic that tries all resolved addresses for a name is pushed down into ConnectSocketByName (picking at random). > * ~The existing addnode logic to prevent multiple connections to the same IP is pushed down into ConnectNode (by storing colliding names into the CNode's addrName field).~ I omitted the last point (commit f9f5cfc) as it conflicts with how our current regtest tests function. ACKs for top commit: furszy: tested ACK 5e79989 random-zebra: ACK 5e79989 and merging Tree-SHA512: 855b471c6eabc08d92ac218d426c915eba45ed640a77bfdb11a02a45efcee21bea45b2c68bbe03b87d63b5f84fd97c1baaee8c18b87f768ee526510838d2cf7e
This is an alternative to #8097 that:
ThreadOpenAddedNodeConnections
andgetaddednodeinfo
, without any DNS resolving from RPC.getaddednodeinfo
(turning it into a dummy)GetAddedNodeInfo
in net.cpp.addnode
logic that tries all resolved addresses for a name is pushed down intoConnectSocketByName
(picking at random).addnode
logic to prevent multiple connections to the same IP is pushed down intoConnectNode
(by storing colliding names into the CNode's addrName field).Untested.