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 proxy address resolution and proxy set.
Let’s start!
Proxy Address Resolution
We concluded last episode inside a for loop, which iterates through all the inputs inside the -proxy argument. After declaring a temporary Proxy object, the software checks whether the proxy_str is empty or if it is equal to 0. If one of the two conditions is false, the if block is not taken into account and the code proceeds directly to another set of instructions.
Proxy proxy;
if (!proxy_str.empty() && proxy_str != "0") {Inside the if clause, instead, the proxy_str is checked to asses if the string represents a Unix Domain Socket1. If so, the Proxy object is initialized with the string. Moreover, the proxyRandomize flag2 is also passed as an input.
if (IsUnixSocketPath(proxy_str)) {
proxy = Proxy{proxy_str, /*tor_stream_isolation=*/proxyRandomize};
} else {
const std::optional<CService> addr{Lookup(proxy_str, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
if (!addr.has_value()) {
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
}
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 proxy_str, the deafult port DEFAULT_TOR_SOCKS_PORT, and fNameLookup, a previously set bool that controls DNS resolution behavior3. 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 an error is returned, otherwise the proxy is initialized with its value.
Finally, proxy is validated. In case IsValid() resolves to false, an initialization error is returned.
if (!proxy.IsValid()) {
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
}
}Set Proxy
After validating the proxy object, the program checks is net_str is empty. If so, each network type is given the same proxy address. On the other end, net_str is checked for the different networks and when a string match is found, the specific network is given the value of the proxy object. If no match is found, an error is returned.
if (net_str.empty()) { // For all networks.
ipv4_proxy = ipv6_proxy = name_proxy = cjdns_proxy = onion_proxy = proxy;
} else if (net_str == "ipv4") {
ipv4_proxy = name_proxy = proxy;
} else if (net_str == "ipv6") {
ipv6_proxy = name_proxy = proxy;
} else if (net_str == "tor" || net_str == "onion") {
onion_proxy = proxy;
} else if (net_str == "cjdns") {
cjdns_proxy = proxy;
} else {
return InitError(strprintf(_("Unrecognized network in -proxy='%s': '%s'"), param_value, net_str));
}
}Here the for loop ends.
Eventually, there is a final check on the validity of the different proxy addresses. Whenever validity is assessed, the proxy for the network is set with the SetProxy function.
if (ipv4_proxy.IsValid()) {
SetProxy(NET_IPV4, ipv4_proxy);
}
if (ipv6_proxy.IsValid()) {
SetProxy(NET_IPV6, ipv6_proxy);
}
if (name_proxy.IsValid()) {
SetNameProxy(name_proxy);
}
if (cjdns_proxy.IsValid()) {
SetProxy(NET_CJDNS, cjdns_proxy);
}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
IBC#015 — Proxy Randomization
IBC#015 — Name Lookup Configuration


