IBC#018: Bitcoin Core Initialization — Part 12
Onion Proxy Configuration
Hello everyone and welcome to this new episode of Inside Bitcoin Code.
A special welcome to the new people that recently subscribed to this newsletter, I hope that you will enjoy what I write. A small suggestion for you: if you know nothing about coding, start reading the posts from Learn2Code to get some basic knowledge before diving in the real deal.
A huge thanks to each of the 145 subscribers of this newsletter and to those who decided to contribute with some sats to this project. It means the world to me!
Today we are going to continue our trip inside the initialization of Bitcoin Core with Onion proxy configuration. [Code Link]
Let’s start!
Onion Proxy Configuration
We finished the latest episode by setting all the proxies for the node connection. The last thing that remains is setting the Onion proxy for Tor connections.
First of all, the code checks if the -onlynet input argument has been added to the configuration of the node and if it is set so as to use Tor. -onlynet allows to restrict usage to the specified network type.
const bool onlynet_used_with_onion{!onlynets.empty() && g_reachable_nets.Contains(NET_ONION)};onlynet_used_with_onion will resolve to true in case the input looks like this, for example:
bitcoind -onlynet=onionThen, the -onion input is retrieved and the resulting string is saved into onionArg. If the string is empty, it means that the connection will use the proxies set with the -proxy argument and the program will completely skip the first if clause.
In case it is equal to 0, it means that the connection to Tor is completely disabled. However, if onlynet_used_with_onion resolves to true, an InitError is return, since -onlynet=onion forbids usage of other network types.
std::string onionArg = args.GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
onion_proxy = Proxy{};
if (onlynet_used_with_onion) {
return InitError(
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
"reaching the Tor network is explicitly forbidden: -onion=0"));
}
}On the other hand, if onionArg contains an Onion address the string is checked to asses if the string represents a Unix Domain Socket. If so, the Onion Proxy object is initialized with the string.
else {
if (IsUnixSocketPath(onionArg)) {
onion_proxy = Proxy(onionArg, /*tor_stream_isolation=*/proxyRandomize);
} else {
const std::optional<CService> addr{Lookup(onionArg, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
if (!addr.has_value() || !addr->IsValid()) {
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
}
onion_proxy = Proxy(addr.value(), /*tor_stream_isolation=*/proxyRandomize);
}
}
}On the other hand, if the string does not represent a Unix Domain Socket the code tries to resolve the network address by using the Lookup() function, which takes as input onionArg, the deafult port DEFAULT_TOR_SOCKS_PORT, and fNameLookup, a previously set bool that controls DNS resolution behavior. The function returns a std::optional<CService> object which contains a value in case of successful lookup or it is empty otherwise.
In case the addr variable is empty or it does not contain a valid address, an error is returned, otherwise the proxy is initialized with its value().
Finally, validity of the onion_proxy is checked. If IsValid() returns true, the Onion proxy is set through the SetProxy() function.
if (onion_proxy.IsValid()) {
SetProxy(NET_ONION, onion_proxy);
} else {
// If -listenonion is set, then we will (try to) connect to the Tor control port
// later from the torcontrol thread and may retrieve the onion proxy from there.
const bool listenonion_disabled{!args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
if (onlynet_used_with_onion && listenonion_disabled) {
return InitError(
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
"reaching the Tor network is not provided: none of -proxy, -onion or "
"-listenonion is given"));
}
g_reachable_nets.Remove(NET_ONION);
}In case of invalid proxy, a fallback mechanism starts. The program will try to connect to Tor using another thread, called torcontrol, later on. This has to be set in the input arguments through -listeonion. If that’s not the case, and onlynet_used_with_onion is true, an InitError is returned. The Onion network type is also removed from the reachable networks.
Let’s keep in touch:
Check out my writings on btc++ insider edition
Try my new app Sats Tracker, an expense tracker app for people living in the Bitcoin standard.
Zap me a coffee and leave me a message: tuma@wallet.yakihonne.com


