Skip to content

Commit 0e2b12b

Browse files
mzumsandevasild
andcommitted
net, init: derive default onion port if a user specified a -port
After port collisions are no longer tolerated but lead to a startup failure in v28.0, local setups of multiple nodes, each with a different -port value would not be possible anymore due to collision of the onion default port - even if the nodes were using tor or not interested in receiving onion inbound connections. Fix this by deriving the onion listening port to be -port + 1. (idea by vasild / laanwj) Co-authored-by: Vasil Dimov <[email protected]>
1 parent e546b4e commit 0e2b12b

File tree

6 files changed

+18
-19
lines changed

6 files changed

+18
-19
lines changed

src/chainparamsbase.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const ChainType chain)
4141
{
4242
switch (chain) {
4343
case ChainType::MAIN:
44-
return std::make_unique<CBaseChainParams>("", 8332, 8334);
44+
return std::make_unique<CBaseChainParams>("", 8332);
4545
case ChainType::TESTNET:
46-
return std::make_unique<CBaseChainParams>("testnet3", 18332, 18334);
46+
return std::make_unique<CBaseChainParams>("testnet3", 18332);
4747
case ChainType::TESTNET4:
48-
return std::make_unique<CBaseChainParams>("testnet4", 48332, 48334);
48+
return std::make_unique<CBaseChainParams>("testnet4", 48332);
4949
case ChainType::SIGNET:
50-
return std::make_unique<CBaseChainParams>("signet", 38332, 38334);
50+
return std::make_unique<CBaseChainParams>("signet", 38332);
5151
case ChainType::REGTEST:
52-
return std::make_unique<CBaseChainParams>("regtest", 18443, 18445);
52+
return std::make_unique<CBaseChainParams>("regtest", 18443);
5353
}
5454
assert(false);
5555
}

src/chainparamsbase.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ class CBaseChainParams
2222
public:
2323
const std::string& DataDir() const { return strDataDir; }
2424
uint16_t RPCPort() const { return m_rpc_port; }
25-
uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; }
2625

2726
CBaseChainParams() = delete;
28-
CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port)
29-
: m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {}
27+
CBaseChainParams(const std::string& data_dir, uint16_t rpc_port)
28+
: m_rpc_port(rpc_port), strDataDir(data_dir) {}
3029

3130
private:
3231
const uint16_t m_rpc_port;
33-
const uint16_t m_onion_service_target_port;
3432
std::string strDataDir;
3533
};
3634

src/init.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
521521
argsman.AddArg("-addnode=<ip>", strprintf("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 %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
522522
argsman.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
523523
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
524-
argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), testnet4BaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
524+
argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultChainParams->GetDefaultPort() + 1, testnetChainParams->GetDefaultPort() + 1, testnet4ChainParams->GetDefaultPort() + 1, signetChainParams->GetDefaultPort() + 1, regtestChainParams->GetDefaultPort() + 1), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
525525
argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
526526
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
527527
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -548,7 +548,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
548548
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
549549
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
550550
argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
551-
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
551+
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md). If set to a value x, the default onion listening port will be set to x+1.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
552552
#ifdef HAVE_SOCKADDR_UN
553553
argsman.AddArg("-proxy=<ip:port|path>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled). May be a local file path prefixed with 'unix:' if the proxy supports it.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION, OptionsCategory::CONNECTION);
554554
#else
@@ -1846,6 +1846,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
18461846
const uint16_t default_bind_port =
18471847
static_cast<uint16_t>(args.GetIntArg("-port", Params().GetDefaultPort()));
18481848

1849+
const uint16_t default_bind_port_onion = default_bind_port + 1;
1850+
18491851
const auto BadPortWarning = [](const char* prefix, uint16_t port) {
18501852
return strprintf(_("%s request to listen on port %u. This port is considered \"bad\" and "
18511853
"thus it is unlikely that any peer will connect to it. See "
@@ -1870,7 +1872,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
18701872
const std::string network_type = bind_arg.substr(index + 1);
18711873
if (network_type == "onion") {
18721874
const std::string truncated_bind_arg = bind_arg.substr(0, index);
1873-
bind_addr = Lookup(truncated_bind_arg, BaseParams().OnionServiceTargetPort(), false);
1875+
bind_addr = Lookup(truncated_bind_arg, default_bind_port_onion, false);
18741876
if (bind_addr.has_value()) {
18751877
connOptions.onion_binds.push_back(bind_addr.value());
18761878
continue;
@@ -1906,7 +1908,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
19061908
} else if (!connOptions.vBinds.empty()) {
19071909
onion_service_target = connOptions.vBinds.front();
19081910
} else {
1909-
onion_service_target = DefaultOnionServiceTarget();
1911+
onion_service_target = DefaultOnionServiceTarget(default_bind_port_onion);
19101912
connOptions.onion_binds.push_back(onion_service_target);
19111913
}
19121914

src/torcontrol.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,9 +711,9 @@ void StopTorControl()
711711
}
712712
}
713713

714-
CService DefaultOnionServiceTarget()
714+
CService DefaultOnionServiceTarget(uint16_t port)
715715
{
716716
struct in_addr onion_service_target;
717717
onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
718-
return {onion_service_target, BaseParams().OnionServiceTargetPort()};
718+
return {onion_service_target, port};
719719
}

src/torcontrol.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void StartTorControl(CService onion_service_target);
2727
void InterruptTorControl();
2828
void StopTorControl();
2929

30-
CService DefaultOnionServiceTarget();
30+
CService DefaultOnionServiceTarget(uint16_t port);
3131

3232
/** Reply from Tor, can be single or multi-line */
3333
class TorControlReply

test/functional/test_framework/test_node.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,9 @@ def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, env=None
221221
extra_args = self.extra_args
222222

223223
# If listening and no -bind is given, then bitcoind would bind P2P ports on
224-
# 0.0.0.0:P and 127.0.0.1:18445 (for incoming Tor connections), where P is
224+
# 0.0.0.0:P and 127.0.0.1:P+1 (for incoming Tor connections), where P is
225225
# a unique port chosen by the test framework and configured as port=P in
226-
# bitcoin.conf. To avoid collisions on 127.0.0.1:18445, change it to
227-
# 127.0.0.1:tor_port().
226+
# bitcoin.conf. To avoid collisions, change it to 127.0.0.1:tor_port().
228227
will_listen = all(e != "-nolisten" and e != "-listen=0" for e in extra_args)
229228
has_explicit_bind = self.has_explicit_bind or any(e.startswith("-bind=") for e in extra_args)
230229
if will_listen and not has_explicit_bind:

0 commit comments

Comments
 (0)