Skip to content

Conversation

@dhruv
Copy link
Contributor

@dhruv dhruv commented Sep 25, 2020

If the user runs: bitcoind -connect=X -seednode=Y, I think it is safe to ignore -seednode. A more populated addrman (via getaddr calls to peers in -seednode) is not useful in this configuration: addrman entries are used to initiate new outbound connections when slots are open, or to open feeler connections and keep addrman from getting stale. This is all done in a part of ThreadOpenConnections (below this line) which is never executed when -connect is supplied. With -connect, ThreadOpenConnections will run this loop and exit thread execution when interrupted.

Reviewers may also find it relevant that when -connect is used, we soft disable -dnsseed in init.cpp perhaps for the same reason i.e. seeding is not useful with -connect.

Running ProcessAddrFetch does not seem to have downside except developer confusion AFAICT. I was confused by this and felt it might affect other new bitcoiners too. If there is strong preference to not remove the line, I'd also be happy to just leave a comment there mentioning ADDR_FETCH/-seednode is irrelevant when used with -connect.

If this change is accepted, the node will still make getaddr calls to peers in -connect and expand addrman. However, disabling those getaddr calls would leak information about the node's configuration.

@DrahtBot DrahtBot added the P2P label Sep 25, 2020
@sipa
Copy link
Member

sipa commented Sep 26, 2020

Concept ACK.

Perhaps we also want a warning that -seednode will be ignored in -connect mode?

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from 42c6b67 to 8208494 Compare September 26, 2020 03:50
@dhruv
Copy link
Contributor Author

dhruv commented Sep 26, 2020

Thank you, @sipa. I've added a log warning as well as a test for it.

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from 8208494 to 8678a6f Compare September 26, 2020 05:02
@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 26, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK mzumsande, vasild, achow101
Concept ACK sipa, jonatack
Stale ACK robot-dreams

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

No conflicts as of last run.

Copy link
Contributor

@robot-dreams robot-dreams left a comment

Choose a reason for hiding this comment

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

Concept ACK, thanks for noticing this case and cleaning it up!

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch 2 times, most recently from 0bbc945 to 50abb30 Compare September 26, 2020 23:32
@dhruv
Copy link
Contributor Author

dhruv commented Sep 29, 2020

Comments above have been addressed. This PR is ready for review.

@robot-dreams
Copy link
Contributor

Thanks for addressing!

One more question: if someone manually sets -dnsseed, so that the SoftSetBoolArg doesn't do anything, is it also worth printing a warning in that case?

I'm asking since it looks like ThreadDNSAddressSeed might also append entries to m_addr_fetches, which is accessed in the (now removed) ProcessAddrFetch call.

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from 50abb30 to a1467aa Compare October 3, 2020 05:48
@dhruv
Copy link
Contributor Author

dhruv commented Oct 3, 2020

Great question, @robot-dreams!

With -connect=X -dnsseed=1, ThreadDNSAddressSeed uses some domains owned by contributors (see CMainParams) to expand the peers in addrman. If -proxy is set, or if a seed domain does not support x9.domain (which tests for NODE_NETWORK | NODE_WITNESS), getaddr calls are made to a peer dns seed resolves to. i.e. ADDR_FETCH connections to an address that a dees like dnsseed.emzy.de resolves to. Otherwise (and this is mostly the case), DNS resolved addresses are used as peer candidates in addrman. So, sometimes, DNS seeds act as seednodes (eg. in -proxy mode) requiring a further getaddr call (this case is affected by removing the ProcessAddrFetch() call), but mostly, they directly dns resolve to peers which support NODE_NETWORK | NODE_WITNESS (this case is unaffected).

if someone manually sets -dnsseed, so that the SoftSetBoolArg doesn't do anything, is it also worth printing a warning in that case?

Yes, I think it's worth adding a warning for the case: -connect=X -dnsseed=1 -proxy=Y. I've added it.

Rebased with master.

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from a1467aa to c9c6388 Compare October 3, 2020 05:58
Copy link
Contributor

@robot-dreams robot-dreams left a comment

Choose a reason for hiding this comment

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

utACK c9c6388b7747032615cb550036d330fb12beedc7

Thanks for looking into the interactions so thoroughly!

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from c9c6388 to a16825b Compare October 3, 2020 22:08
@robot-dreams
Copy link
Contributor

utACK a16825b42190a2780baeb7a262c9b6cda57a2755

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

Tested Concept ACK

Could/should the warnings be placed in the -connect section of InitParameterInteraction() and logged at the top along with the other parameter interactions?

$ ./src/bitcoind -regtest -connect=fakeaddress1 -seednode=fakeaddress2
2020-10-04T12:22:30Z Bitcoin Core version v0.20.99.0-a16825b421-dirty (debug build)
2020-10-04T12:22:30Z InitParameterInteraction: parameter interaction: -connect set -> setting -dnsseed=0
2020-10-04T12:22:30Z InitParameterInteraction: parameter interaction: -connect set -> setting -listen=0

src/init.cpp Outdated
Copy link
Member

Choose a reason for hiding this comment

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

maybe s/in -connect mode/when -connect is used/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

src/init.cpp Outdated
Copy link
Member

Choose a reason for hiding this comment

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

maybe s/in -connect mode when/when -connect is used and/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

src/init.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

This could have gone inside the condition right above.

Copy link
Contributor Author

@dhruv dhruv Oct 8, 2020

Choose a reason for hiding this comment

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

The condition above is true when connect.size() == 0 (happens in the -noconnect -seednode=fakeaddress test case) and the new condition is not.

I could move the whole condition inside as-is, but wouldn't gain in clarity or brevity.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess @naumenkogs meant this:

if (connect.size() != 1 || connect[0] != "0") {
    connOptions.m_specified_outgoing = connect;

    if (!connOptions.vSeedNodes.empty()) {
        LogPrintf("-seednode is ignored when -connect is used\n");
    }
}

src/init.cpp Outdated
Copy link
Contributor

@naumenkogs naumenkogs Oct 6, 2020

Choose a reason for hiding this comment

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

But this is true even if no -connect is configured? Then the warning is confusing...
Perhaps move this into the block above (same suggestion there)?

Copy link
Contributor

@naumenkogs naumenkogs Oct 6, 2020

Choose a reason for hiding this comment

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

Warning says -dnsseed is ignored. But it will be shown even if a user haven't touched -dnsseed at all, just when they configured a -proxy. Feels like bad UX.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reg. the first comment: If the configuration is -dnsseed=1 -proxy=X, ThreadDNSAddressSeed will queue ADDR_FETCH connections and they will get processed because ThreadOpenConnections will invoke ProcessAddrFetch with some frequency. (This will no longer happen when using -connect=X -dnsseed=1 -proxy=X after this PR is merged)

Reg. the second comment: You're right. If the configuration is -connect=X -proxy=Y, the log would print and the user might be confused. I have updated the code to check explicitly that the user set the arg. I have also added a test case to confirm the same.

@naumenkogs
Copy link
Contributor

I find it hard to navigate this PR and make sense of everything.
Could you split it into commits with separate concerns and add meaningful commit messages? Similar to your PR original post, but with less uncertainty :)

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from a16825b to 0b59d7b Compare October 8, 2020 17:52
Copy link
Contributor Author

@dhruv dhruv left a comment

Choose a reason for hiding this comment

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

Thank you for thorough and educational reviews, @jonatack, @naumenkogs ! I have pushed up changes and rebased master since since I had to force push anyway.

src/init.cpp Outdated
Copy link
Contributor Author

@dhruv dhruv Oct 8, 2020

Choose a reason for hiding this comment

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

The condition above is true when connect.size() == 0 (happens in the -noconnect -seednode=fakeaddress test case) and the new condition is not.

I could move the whole condition inside as-is, but wouldn't gain in clarity or brevity.

src/init.cpp Outdated
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

src/init.cpp Outdated
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reg. the first comment: If the configuration is -dnsseed=1 -proxy=X, ThreadDNSAddressSeed will queue ADDR_FETCH connections and they will get processed because ThreadOpenConnections will invoke ProcessAddrFetch with some frequency. (This will no longer happen when using -connect=X -dnsseed=1 -proxy=X after this PR is merged)

Reg. the second comment: You're right. If the configuration is -connect=X -proxy=Y, the log would print and the user might be confused. I have updated the code to check explicitly that the user set the arg. I have also added a test case to confirm the same.

src/init.cpp Outdated
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@dhruv
Copy link
Contributor Author

dhruv commented Oct 8, 2020

Could/should the warnings be placed in the -connect section of InitParameterInteraction() and logged at the top along with the other parameter interactions?

@jonatack I'd actually have liked that too, but the place it is right now also checks for -connect=0. I was trying to avoid replicating that check as it is an unintuitive one.

@dhruv
Copy link
Contributor Author

dhruv commented Oct 8, 2020

Could you split it into commits with separate concerns and add meaningful commit messages? Similar to your PR original post, but with less uncertainty :)

@naumenkogs I can definitely do that if it makes sense for commit atomicity. Since the actual change is only removing the ProcessAddrFetch line in ThreadOpenConnections and every thing else (the log warnings, tests, etc.) support that change, I thought we would need all that in one commit for the history to make sense. Thoughts?

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch 2 times, most recently from 4609c75 to b485325 Compare October 8, 2020 18:46
@dhruv
Copy link
Contributor Author

dhruv commented Mar 12, 2021

Rebased. Ready for further review.

@achow101
Copy link
Member

Are you still working on this?

@glozow glozow requested a review from mzumsande October 12, 2022 18:19
@dhruv
Copy link
Contributor Author

dhruv commented Oct 12, 2022

@achow101 yes

@maflcko
Copy link
Member

maflcko commented Oct 13, 2022

Mind doing a rebase, otherwise it will be harder to review, given all the other related changes in the meantime

@dhruv
Copy link
Contributor Author

dhruv commented Oct 14, 2022

@MarcoFalke working through bip324 PRs to bring them up to date with the released draft and I'll get to the rebases right after that.

Copy link
Contributor

@mzumsande mzumsande left a comment

Choose a reason for hiding this comment

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

Concept ACK

I agree that the call to ProcessAddrFetch() is unnecessary when -connect is used - I don't see a use case for harvesting addresses that you'll never use.

Automatic rebase on master seems to work fine without any silent conflicts.

In principle, we could disable various other unnecessary things related to addr relay in -connect mode (e.g. sending out GETADDR messages) in follow-ups, but this would mean making the existing code more complicated and I'm not convinced that's worth it.

Copy link
Contributor

@mzumsande mzumsande Oct 18, 2022

Choose a reason for hiding this comment

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

If -proxy is set, or if a seed domain does not support x9.domain (which tests for NODE_NETWORK | NODE_WITNESS), getaddr calls are made to the dns seed itself as a peer. i.e. ADDR_FETCH connections to an address like dnsseed.emzy.de.

I used to think the same, but @sipa explained to me that this is not what's happening: We don't make a ADDR_FETCH connection to a node run by the DNS seed, in fact the DNS seed operator does not even need to run a reachable bitcoind node. Instead, we connect to the peer that the DNS seed currently resolves to - which is basically just a random node on the network not under the control of the DNS seed operator, and it changes every once in a while (~30minutes?) for a given DNS seed.
Since this is a common misconception, I think it would be good to describe it not just here in the test code, but also in net (If you'd prefer not to do it here, I could open a PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yeah, he mentioned this to me as well. Embarrassingly, I forgot to update this PR. Updated this comment, added a comment in net and updated a PR comment from me to @robot-dreams as well to reflect this.

@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from 03c2bff to bcb9541 Compare October 18, 2022 16:38
@dhruv dhruv force-pushed the seednode-not-needed-with-connect branch from bcb9541 to 2555a39 Compare October 18, 2022 16:51
@dhruv
Copy link
Contributor Author

dhruv commented Oct 18, 2022

Automatic rebase on master seems to work fine without any silent conflicts.

Thanks, @mzumsande! Rebased.

In principle, we could disable various other unnecessary things related to addr relay in -connect mode (e.g. sending out GETADDR messages)

See my OP in the PR. I thought about this, but then realized that this would mean the node we are -connected to will be able to fingerprint that's our configuration and make it clear that we are vulnerable to eclipse attacks. Thoughts?

I agree though, if we want to do that at all, we do it in a followup.

@mzumsande
Copy link
Contributor

Code Review ACK 2555a39

See my OP in the PR. I thought about this, but then realized that this would mean the node we are -connected to will be able to fingerprint that's our configuration and make it clear that we are vulnerable to eclipse attacks. Thoughts?

Oops, missed this. I agree, fingerprinting is another good reason. I think in practice we'd often trust the node we -connect to more than a random peer, and if this is our only connection to the network, the peer could guess this anyway by the lack of transactions / blocks /addresses we advertise to them.
In general, it is probably not worth optimizing -connect mode too much by adding conditionals at various spots in net_processing just to save a few bytes of bandwidth or memory here and there, because it's a rather special-purpose way of running a node used only in rare occasions.

@fanquake fanquake requested review from naumenkogs and vasild October 20, 2022 00:30
Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 2555a39

@fanquake
Copy link
Member

cc @ryanofsky from a settings / init pov.

@achow101
Copy link
Member

ACK 2555a39

@achow101 achow101 merged commit f722a9b into bitcoin:master Feb 17, 2023
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 17, 2023
…if -connect is specified

2555a39 p2p: ProcessAddrFetch(-seednode) is unnecessary if -connect is specified (Dhruv Mehta)

Pull request description:

  If the user runs: `bitcoind -connect=X -seednode=Y`, I _think_ it is safe to ignore `-seednode`. A more populated `addrman` (via `getaddr` calls to peers in `-seednode`) is not useful in this configuration: `addrman` entries are used to initiate new outbound connections when slots are open, or to open feeler connections and keep `addrman` from getting stale. This is all done in a part of `ThreadOpenConnections` (below [this line](https://github.com/bitcoin/bitcoin/blob/master/src/net.cpp#L1803)) which is never executed when `-connect` is supplied. With `-connect`, `ThreadOpenConnections` will run [this loop](https://github.com/bitcoin/bitcoin/blob/master/src/net.cpp#L1785) and exit thread execution when interrupted.

  Reviewers may also find it relevant that when `-connect` is used, we [soft disable](https://github.com/bitcoin/bitcoin/blob/master/src/init.cpp#L800) `-dnsseed` in init.cpp perhaps for the same reason i.e. seeding is not useful with `-connect`.

  Running `ProcessAddrFetch` does not seem to have downside except developer confusion AFAICT. I was confused by this and felt it might affect other new bitcoiners too. If there is strong preference to not remove the line, I'd also be happy to just leave a comment there mentioning `ADDR_FETCH`/`-seednode` is irrelevant when used with `-connect`.

  If this change is accepted, the node will still make `getaddr` calls to peers in `-connect` and expand `addrman`. However, disabling those `getaddr` calls would leak information about the node's configuration.

ACKs for top commit:
  mzumsande:
    Code Review ACK 2555a39
  achow101:
    ACK 2555a39
  vasild:
    ACK 2555a39

Tree-SHA512: 9187a0cff58db8edeca7e15379b1c121e7ebe8c38fb82f69e3dae8846ee94c92a329d79025e0f023c7579b2d86e7dbf756e4e30e90a72236bfcd2c00714180b3
@bitcoin bitcoin locked and limited conversation to collaborators Feb 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.