Skip to content

Conversation

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Dec 11, 2016

Previously addnodes were in competition with outbound connections
for access to the eight outbound slots.

One result of this is that frequently a node with several addnode
configured peers would end up connected to none of them, because
while the addnode loop was in its two minute sleep the automatic
connection logic would fill any free slots with random peers.
This is particularly unwelcome to users trying to maintain links
to specific nodes for fast block relay or monitoring purposes.

Another result is that a group of nine or more nodes which are
have addnode configured towards each other can become partitioned
from the public network.

This commit introduces a new limit of eight connections just for
addnode peers which is not subject to any of the other connection
limitations (including maxconnections).

The choice of eight is sufficient so that under no condition would
a user find themselves connected to fewer addnoded peers than
previously. It is also low enough that users who are confused
about the significance of more connections and have gotten too
copy-and-paste happy will not consume more than twice the slot
usage of a typical user.

Any additional load on the network resulting from this will likely
be offset by a reduction in users applying even more wasteful
workaround for the prior behavior.

The retry delays are reduced to avoid nodes sitting around without
their added peers up, but are still sufficient to prevent overly
aggressive repeated connections. The reduced delays also make
the system much more responsive to the addnode RPC.

Ban-disconnects are also exempted for peers added via addnode since
the outbound addnode logic ignores bans. Previously it would ban
an addnode then immediately reconnect to it.

A minor change was also made to CSemaphoreGrant so that it is
possible to re-acquire via an object whos grant was moved.

@fanquake fanquake added the P2P label Dec 11, 2016
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.

Are addnode connections no longer counted under the normal max connection limit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They are not. See also commit message, pr text, and release note. :)

@CodeShark
Copy link
Contributor

concept ACK

Copy link
Contributor

Choose a reason for hiding this comment

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

What do you mean by "aggressive"connection here?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is new behaviour, addnoded nodes are not punished/banned. Right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"Ban-disconnects are also exempted for peers added via addnode since
the outbound addnode logic ignores bans. Previously it would ban
an addnode then immediately reconnect to it."

src/rpc/net.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.

addnode missing in the helptext.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

@laanwj
Copy link
Member

laanwj commented Dec 15, 2016

Adding a specific limit for user-added nodes makes it easier to reason about, and avoids some annoying edge cases. Good idea. Concept ACK.

@TheBlueMatt
Copy link
Contributor

ACK b8d170dab441896970d5ab0f15ca672173592065

Would very much like to see this for 0.14.

@maflcko maflcko added this to the 0.14.0 milestone Dec 25, 2016
src/net.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.

If no connection was established, this sleep runs while holding the semaphore. Is that a problem? I think this is the only thread that accesses the semaphore, but if that's the case... why are we using a semaphore?

Copy link
Contributor Author

@gmaxwell gmaxwell Dec 29, 2016

Choose a reason for hiding this comment

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

It's okay to hold extras here because this is the only place they're taken. What they're used for is to sleep until a release, which is also the case for outbound peers use of a semaphore. The result is so that when this thread is inactive because we're at connection maximum and a connection goes down the code to make a new connection begins instantly.

Perhaps it would be better to use some other notification mechanism; e.g. a sleep that can wake early on a condition variable, triggered whenever an addnoded peer is disconnected... but this is what the outbound connections currently do, and I didn't see a reason to make them any different. If you want I could add a change to rework both to whatever mechanism you prefer. The goal should be that if we're sleeping because there is nothing else to do (because we're at our limit, or because we have no down addnodes to try) we ought to wake instantly when a disconnection (or rpc reconfiguration, I guess) potentially changes that situation.

Copy link
Member

Choose a reason for hiding this comment

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

We'll soon have an OnDisconnected() event that will allow us to change this (and possibly the outbound behavior) more easily. Using the same mechanism here makes sense for now, imo.

src/net.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.

This makes addnoded connections no longer prevent random connections to the same netgroups. Is that change implied by "which is not subject to any of the other connection limitations"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was the intent. At least the idea was to make the automatic and addnode connections operate largely independent of each other, not auto-connecting to amazon because you've got an addnode to amazon seems odd.

At least my perspective on the netgroup limitation is that with your limited 8 outbound slots you don't want to harm your partition resistance by spending multiple of them on a single netgroup. That no longer applies when addnodes are not consuming your outbound slots, just like it doesn't apply to inbound peers. (though inbound has a stronger additional reason: they're attacker controlled).

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense. I just wanted to make sure it was intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you think I should add a comment like, "Inbound and addnode connections don't use our limited pool of automatic outbound connections, so we don't consider them for netgroup exclusion."?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, always add comments :).

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

@sipa
Copy link
Member

sipa commented Dec 30, 2016

One nit: your last commit has 'documnetation' in the title.

@sipa
Copy link
Member

sipa commented Dec 30, 2016

utACK 1c7dcacabd7327273a138aec4fd74a404b32e596

@kanoi
Copy link

kanoi commented Jan 1, 2017

Missing command line and RPC options to set the limit.

@maflcko
Copy link
Member

maflcko commented Jan 1, 2017

@kanoi You can find the reasons why this is not supported in #9217 and similar discussions.

@kanoi
Copy link

kanoi commented Jan 2, 2017

That discussion is only about RPC.

@TheBlueMatt
Copy link
Contributor

@kanoi that discussion is about outbound connection P2P slots, not RPC. The issue here is that lots of folks configure Bitcoin Core by adding a long list of known IP addresses from arbitrary sources to addnode. This used to be especially common, but still exists today. In those cases, we absolutely cannot default to simply make 100 outbound connections (for the same reasons as discussed in #9217).

@kanoi
Copy link

kanoi commented Jan 2, 2017

Nothing to do with defaults - I'm referring to having an arbitrary constant number that can't be changed without modifying the code - there's no logical reason to set it at 8 and enforce that number for eternity.
Default of 8 is not the issue, forcing it to always be 8 is the issue.

@TheBlueMatt
Copy link
Contributor

@kanoi changing the maximum outbound connections is far out of scope for this PR. If you wish to do so, please comment on #9217, #6533, #6014, etc.

@kanoi
Copy link

kanoi commented Jan 2, 2017

I don't see the reason for adding a new setting and ignoring adding an option to configure it.
If the setting isn't necessary then why add it.
If the setting is necessary, why not allow it to be configured.

@TheBlueMatt
Copy link
Contributor

There is no new setting here? It uses the same connection slot count as previously (8).

@kanoi
Copy link

kanoi commented Jan 2, 2017

Really?

This commit introduces a new limit of eight connections just for
addnode peers which is not subject to any of the other connection
limitations (including maxconnections).

@sipa
Copy link
Member

sipa commented Jan 2, 2017 via email

Copy link
Member

@theuni theuni left a comment

Choose a reason for hiding this comment

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

utACK. I like having added connections independent of the automatic ones. As-is, it's been unclear what should take precedence in some cases.

src/net.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.

We'll soon have an OnDisconnected() event that will allow us to change this (and possibly the outbound behavior) more easily. Using the same mechanism here makes sense for now, imo.

@TheBlueMatt
Copy link
Contributor

Needs rebase, should be easy.

@laanwj
Copy link
Member

laanwj commented Jan 5, 2017

Conflicts:

<<<<<<< 406f35d99d0fcd2f50370280e605283d04da466a
                OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
                if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
                    return;
||||||| merged common ancestors
                OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
                MilliSleep(500);
=======
                OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false, false, true);
                MilliSleep(500);
>>>>>>> Break addnode out from the outbound connection limits.
            }
        }
<<<<<<< 406f35d99d0fcd2f50370280e605283d04da466a
        if (!interruptNet.sleep_for(std::chrono::minutes(2)))
            return;
||||||| merged common ancestors

        MilliSleep(120000); // Retry every 2 minutes
=======
        MilliSleep(tried ? 60000 : 2000); // Retry every 60 seconds if a connection was attempted, otherwise two seconds
>>>>>>> Break addnode out from the outbound connection limits.

Previously addnodes were in competition with outbound connections
 for access to the eight outbound slots.

One result of this is that frequently a node with several addnode
 configured peers would end up connected to none of them, because
 while the addnode loop was in its two minute sleep the automatic
 connection logic would fill any free slots with random peers.
 This is particularly unwelcome to users trying to maintain links
 to specific nodes for fast block relay or purposes.

Another result is that a group of nine or more nodes which are
 have addnode configured towards each other can become partitioned
 from the public network.

This commit introduces a new limit of eight connections just for
 addnode peers which is not subject to any of the other connection
 limitations (including maxconnections).

The choice of eight is sufficient so that under no condition would
 a user find themselves connected to fewer addnoded peers than
 previously.  It is also low enough that users who are confused
 about the significance of more connections and have gotten too
 copy-and-paste happy will not consume more than twice the slot
 usage of a typical user.

Any additional load on the network resulting from this will likely
 be offset by a reduction in users applying even more wasteful
 workaround for the prior behavior.

The retry delays are reduced to avoid nodes sitting around without
 their added peers up, but are still sufficient to prevent overly
 aggressive repeated connections.  The reduced delays also make
 the system much more responsive to the addnode RPC.

Ban-disconnects are also exempted for peers added via addnode since
 the outbound addnode logic ignores bans.  Previously it would ban
 an addnode then immediately reconnect to it.

A minor change was also made to CSemaphoreGrant so that it is
 possible to re-acquire via an object whos grant was moved.
Also adds a comment about the netgroup exclusion behavior.
@gmaxwell
Copy link
Contributor Author

gmaxwell commented Jan 5, 2017

rebased.

@sipa
Copy link
Member

sipa commented Jan 5, 2017

utACK 032ba3f

@TheBlueMatt
Copy link
Contributor

Diff looks equivalent to me from my previous ACK at b8d170dab441896970d5ab0f15ca672173592065 to 032ba3f

@sipa sipa merged commit 032ba3f into bitcoin:master Jan 6, 2017
sipa added a commit that referenced this pull request Jan 6, 2017
032ba3f RPC help documentation for addnode peerinfo. (Gregory Maxwell)
90f13e1 Add release notes for addnode changes. (Gregory Maxwell)
50bd12c Break addnode out from the outbound connection limits. (Gregory Maxwell)
}
if (!interruptNet.sleep_for(std::chrono::minutes(2)))
// Retry every 60 seconds if a connection was attempted, otherwise two seconds
if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)));
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, I'm getting a warning for this on macOS 10.12.

net.cpp:1807:75: warning: if statement has empty body [-Wempty-body]
        if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)));
                                                                          ^
net.cpp:1807:75: note: put the semicolon on a separate line to silence this warning

Looks like a stray semicolon to me. For reference in the future, if I come across something like this again, should I bring this to the attention of the engineer, or should I just file a PR if the commit has already occurred?

Copy link
Member

Choose a reason for hiding this comment

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

@droark If it is not merged, provide feedback. After it is merged, pull requests are very welcomed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. Just filed #9487.

droark pushed a commit to droark/bitcoin that referenced this pull request Jan 7, 2017
Empty body introduced by commit bitcoin#9319 should not be empty.
@btcdrak
Copy link
Contributor

btcdrak commented Jan 7, 2017

Post humus ACK 032ba3f

codablock pushed a commit to codablock/dash that referenced this pull request Jan 18, 2018
…mits.

032ba3f RPC help documentation for addnode peerinfo. (Gregory Maxwell)
90f13e1 Add release notes for addnode changes. (Gregory Maxwell)
50bd12c Break addnode out from the outbound connection limits. (Gregory Maxwell)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
…mits.

032ba3f RPC help documentation for addnode peerinfo. (Gregory Maxwell)
90f13e1 Add release notes for addnode changes. (Gregory Maxwell)
50bd12c Break addnode out from the outbound connection limits. (Gregory Maxwell)
lateminer pushed a commit to lateminer/bitcoin that referenced this pull request Jan 10, 2019
Empty body introduced by commit bitcoin#9319 should not be empty.
CryptoCentric pushed a commit to absolute-community/absolute that referenced this pull request Feb 26, 2019
…mits.

032ba3f RPC help documentation for addnode peerinfo. (Gregory Maxwell)
90f13e1 Add release notes for addnode changes. (Gregory Maxwell)
50bd12c Break addnode out from the outbound connection limits. (Gregory Maxwell)
laanwj added a commit that referenced this pull request May 5, 2021
…ections config options

b4fcbcf doc: update -maxconnections config option help (Jon Atack)
79685a8 doc: update -addnode config option help (Jon Atack)
2896c6c doc: update addnode rpc help (Jon Atack)

Pull request description:

  Since #9319 proposed by Gregory Maxwell and released in v0.14, peers manually added through the `-addnode` config option or using the `addnode` RPC have their own separate limit of 8 connections that does not compete with other inbound or outbound connection usage and is not subject to the limitation imposed by the `-maxconnections` option.

  This PR updates the `-addnode` and `-maxconnections` config options and the `addnode` RPC help docs with this information.

  `-addnode` config option help
  ```
  $ bitcoind -h | grep -A5 addnode=
    -addnode=<ip>
         Add a node to connect to and attempt to keep the connection open (see
         the addnode RPC help for more info). This option can be specified
         multiple times to add multiple nodes; connections are limited to
         8 at a time and are counted separately from the -maxconnections
         limit.

  $ bitcoind -h | grep -A3 maxconnections=
    -maxconnections=<n>
         Maintain at most <n> connections to peers (default: 125). This limit
         does not apply to connections manually added via -addnode or the
         addnode RPC, which have a separate limit of 8.
  ```

  `addnode` rpc help
  ```
  $ bitcoin-cli help addnode
  addnode "node" "command"

  Attempts to add or remove a node from the addnode list.
  Or try a connection to a node once.
  Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be
  full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).
  Addnode connections are limited to 8 at a time and are counted separately from the -maxconnections limit.
  ```

ACKs for top commit:
  prayank23:
    ACK b4fcbcf
  jarolrod:
    ACK b4fcbcf

Tree-SHA512: b6d69baa6cbf6d53f91bac5b39b549d49db6c95f92ea1bdd3588a6432794a25ac2c8b3c89e2c72bb9097e61f2717c8b5ecc404745d5992b88e523db03200898f
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 5, 2021
…maxconnections config options

b4fcbcf doc: update -maxconnections config option help (Jon Atack)
79685a8 doc: update -addnode config option help (Jon Atack)
2896c6c doc: update addnode rpc help (Jon Atack)

Pull request description:

  Since bitcoin#9319 proposed by Gregory Maxwell and released in v0.14, peers manually added through the `-addnode` config option or using the `addnode` RPC have their own separate limit of 8 connections that does not compete with other inbound or outbound connection usage and is not subject to the limitation imposed by the `-maxconnections` option.

  This PR updates the `-addnode` and `-maxconnections` config options and the `addnode` RPC help docs with this information.

  `-addnode` config option help
  ```
  $ bitcoind -h | grep -A5 addnode=
    -addnode=<ip>
         Add a node to connect to and attempt to keep the connection open (see
         the addnode RPC help for more info). This option can be specified
         multiple times to add multiple nodes; connections are limited to
         8 at a time and are counted separately from the -maxconnections
         limit.

  $ bitcoind -h | grep -A3 maxconnections=
    -maxconnections=<n>
         Maintain at most <n> connections to peers (default: 125). This limit
         does not apply to connections manually added via -addnode or the
         addnode RPC, which have a separate limit of 8.
  ```

  `addnode` rpc help
  ```
  $ bitcoin-cli help addnode
  addnode "node" "command"

  Attempts to add or remove a node from the addnode list.
  Or try a connection to a node once.
  Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be
  full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).
  Addnode connections are limited to 8 at a time and are counted separately from the -maxconnections limit.
  ```

ACKs for top commit:
  prayank23:
    ACK bitcoin@b4fcbcf
  jarolrod:
    ACK b4fcbcf

Tree-SHA512: b6d69baa6cbf6d53f91bac5b39b549d49db6c95f92ea1bdd3588a6432794a25ac2c8b3c89e2c72bb9097e61f2717c8b5ecc404745d5992b88e523db03200898f
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.