I'm trying to figure out if we can create an outgoing connection to a inbound node (a node which we are already connected to, but the remote peer has initiated the connection). I know that this does not make much sense since we exchange information to inbound and outbound nodes. However, I have looked at the source code and did not find the code that prevents a node from doing that. Is anyone out there more successful?
2 Answers
Nothing prevents this as it is impossible to distinguish whether the node that is connecting to you is the same one that you are already connected to. This is because one machine can run multiple node software or multiple instances of the same software and thus it can be multiple nodes on the network.
There's also no reason to block such a connection.
-
I see that there is no reason to block such a connection. However, as I see it, a node would benefit if it connects to another node (and not to a one it is already connected to). Can't we use the IP address? May 20, 2019 at 7:00
-
No. IP addresses are not unique enough identifiers. Besides what I mentioned, there's also the issue of NATs. Two computers behind a NAT will have the same public IP address.– Andrew Chow ♦May 20, 2019 at 15:24
Jan,
there is a mechanism that prevents Bitcoin Core from opening a new connection (making an outbound) to an address it is already connected to (irrelevant of whether the existent connection is inbound or outbound).
See the function CConnman::AlreadyConnectedToAddress()
, how it is called from CConnman::OpenNetworkConnection()
and the surrounding code.
This check, however, could allow to open an outbound even if an inbound from the same address exists in the following cases:
- When opening an outbound connection to RPC
addnode onetry
, RPCaddconnection
,ADDR_FETCH
connections, connections to addresses given to-connect
and-addnode
. Then the port is also compared. So, for sure, we are not going to see an inbound connection from the node's listening port (e.g.addr:8333
) during the check. Inbound connection are from some random port assigned by the remote node's operating system (e.g.addr:54721
). In these cases the check would only prevent us from opening multiple outbound connections to the same node.
In the other cases only the address is compared, without the port, so the check would detect an existent inbound from addr:54721
when trying to connect to addr:8333
and would cancel the opening of the connection. However:
- There is a race in
CConnman::OpenNetworkConnection()
, ifaddr
connects to us between the two:
- check whether connected to
addr
- if not, then open a connection to
addr
This race is rare because the window is very small, but more likely if the network is slow and completing the connection takes some time, like could be with overlay networks, especially I2P.