比特币源码研读之二十五

我们今天将继续深入AppInitMain函数,下面我们一起来对其进行详细分析。

src/bitcond.cpp、src/init.h、src/init.cpp、src/util.h、src/util.cpp、src/net.h、src/net.cpp、src/net_address.h、src/net_address.cpp、src/netbase.h、src/netbase.cpp

一、设置代理

proxyrandomize参数是在0.11.0版本中加入的,该版本发布于2015年7月12日。该参数的作用是让比特币网络节点可以同时连接多个不同的节点,避免连接到恶意节点或者P2P网络中被禁止的节点,提升了连接稳定性的同时也提高了隐私性,这些方面的提升在节点初始化时尤为明显。

(原文见:https://bitcoin.org/en/release/v0.11.0#privacy-disable-wallet-transaction-broadcast)

该参数的解析代码如下:

bool proxyRandomize =GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);

从上面的代码我们可以看到该参数的默认值为DEFAULT_PROXYRANDOMIZE,其定义位于init.cpp中:

static const bool DEFAULT_PROXYRANDOMIZE = true;

该参数的默认值为true,也就是说就算我们自己启动的时候没有显示设置该参数,随机代理功能是生效的。该参数主要用于后续的代理

代理参数解析代码如下:

std::string proxyArg =GetArg("-proxy", "");

通过上面的代码我们可以看到,默认情况下比特币节点是不设置代理地址的,其代理地址一般为空,我们先来看下代理设置参数-proxy的注释:

// -proxy sets a proxy for all outgoing networktraffic

// -noproxy (or -proxy=0) as well as the empty stringcan be used to not set a proxy, this is the default

从注释我们可以了解到如果设置了代理地址,proxy将为节点所有输出连接提供代理地址,-noproxy或者-proxy=0的情况下将不设置代理地址。

随后的SetLimited(NET_TOR)代码是限制与TOR匿名网络的连接,如果设置了proxy代理地址,并且有效,才能连接匿名网络,如代码所示:

if (proxyArg !="" && proxyArg != "0") {

  CServiceresolved(LookupNumeric(proxyArg.c_str(), 9050));

  proxyType addrProxy = proxyType(resolved,proxyRandomize);

  if (!addrProxy.IsValid())

    return InitError(strprintf(_("Invalid-proxy address: '%s'"), proxyArg));

    SetProxy(NET_IPV4, addrProxy);

    SetProxy(NET_IPV6, addrProxy);

    SetProxy(NET_TOR, addrProxy);

    SetNameProxy(addrProxy);

    SetLimited(NET_TOR,false); // by default, -proxy sets onion as reachable, unless -noonion later

    }

在上面的代理中我们首先来看CService类,该类是CNetAddr的基类,二者的定义均在netaddress.h中。CNetAddr是IP地址封装类,CService在IP地址的基础上增加了TCP端口号,形式为IP:端口号,更具体的例子是192.168.1.1:8080。

通过CServiceresolved(LookupNumeric(proxyArg.c_str(), 9050));代码实现将代理地址传入到CService对象resolved中,其中LookupNumeric是将IP与端口字符串转换为IP地址与端口。如果我们在proxy参数中未设置端口号或者设置错了端口号将默认采用9050端口。随后将resolved与proxyRandomize参数传入proxyType类的对象中,proxyType类定义于netbase.h中,然后判断addrProxy的有效性,其实是判断resolved的有效性,即解析后的IP与端口是否有效,如果无效则程序退出,反之将对IPV4、IPV6以及Tor设置该代理,从而可以连接至所有网络中。

二、设置洋葱路由

设置洋葱路由与前面代理地址类似,只是此处指针对Tor网络设置代理地址,其解析过程与proxy类似,均为传入IP+端口方式,此处不再赘述。

三、网络设置外部参数解析

此处涉及的新外部参数主要包括listen、discover、dns、blocksonly以及externnalip,这几个参数的含义如下:

-listen:监听的外部连接IP地址,具体见我简书专栏中的《比特币源码研读之八》

-discover:发现配置文件中存储的默认IP地址,具体见我简书专栏中的《比特币源码研读之八》

-blocksonly:节点进入blocksonly模式,具体见我简书专栏中的《比特币源码研读之十六》

-externalip=ip:指定自身的外部IP地址,具体见我简书专栏中的《比特币源码研读之八》。

其他参数的含义也在《比特币源码研读之八》还有其他文章中已详细说明,此处不再详述。

我的简书专栏:https://www.jianshu.com/u/30081a05cf95

四、ZMQ消息管理中间件

ZMQ是一个消息管理中间件,通过它我们可以实现消息的订阅、发布、节点之间的消息通信。ZMQ的官方解释如下:

ZMQ (以下 ZeroMQ 简称 ZMQ)是一个简单好用的传输层,像框架一样的一个 socket library,他使得 Socket 编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ 的明确目标是“成为标准网络协议栈的一部分,之后进入 Linux 内核”。现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD 套接字之上的一层封装。ZMQ 让编写高性能网络应用程序极为简单和有趣。

具体内容可参考或者自行百度:

https://blog.csdn.net/lengye7/article/details/80370611?utm_source=copy

在比特币网络中,我们可以通过订阅比特币核心的ZMQ消息,即时高效地接收区块更新、交易更新等消息,可以达到近实时的通信效果。但前提是ZMQ消息接口是打开的,其打开定义是通过ENABLE_ZMQ来实现的,而ENABLE_ZMQ则是在比特币源码编译时就需要设置的,如果编译环境中有zmq的库,同时设置链接该库,那ENABLE_ZMQ将为true,进而就可以使用zmq消息管理库。

最后要提到的是最大上传速度参数maxuploadtarget,其单位为MiB/24小时,如果该参数的值为0,将不限制输出速度。其默认是DEFAULT_MAX_UPLOAD_TARGET即为0,意思是默认不限制对外上传速度。

五、结束语

以上即为设置代理、设置洋葱路由、网络相关外部参数解析以及ZMQ等内容的代码研读,这些内容与前文一样,都属于比特币网络相关的初始化过程,比特币网络的初始化过程到此已结束,我将在后面的文章中详细解读区块链加载的代码,敬请期待!

推荐阅读更多精彩内容