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