比特币源码研读(11)-main函数
上次,我们分析了比特币的日志信息打印。今天我们继续分析下面的代码。
InitParameterInteraction();该函数位于init.cpp文件种。
从函数名字,我们可以初步了解,这是对输入参数的处理。
这里设计到的一些基本内容,这里监听的地址是其他节点的地址,监听方式如下
-bind,绑定监听地址,方式1
-whitebind,绑定监听地址,方式2
-connect,是否连接可信任节点
-proxy,代理模式,不需要监听(listen)
-listen,是否监听默认地址
-externalip,外部IP设置
-blocksonly,区块模式
-whitelistforcerelay,白名单模式
函数分析如下:
// whenspecifying an explicit binding address, you want to listen on it
// even when-connect or -proxy is specified
注释的意思是,当详细定义了一个地址以后,即使设置了-connect和proxy参数,程序也会监听这个地址(这一点,后文有详细说明)
1)绑定并监听地址
if (gArgs.IsArgSet("-bind")) {
if(gArgs.SoftSetBoolArg("-listen", true))
LogPrintf("%s: parameter interaction: -bind set -> setting-listen=1\n", __func__);
}
if(gArgs.IsArgSet("-whitebind")) {
if(gArgs.SoftSetBoolArg("-listen", true))
LogPrintf("%s: parameter interaction: -whitebind set -> setting-listen=1\n", __func__);
}
绑定地址的方式有两种,-blnd和-whitebind,软件对这两种参数的处理方式是一样的,如果绑定了地址,那么通过函数SoftSetBoolArg将listen设置为true
2)连接可信节点
if(gArgs.IsArgSet("-connect")) {
// when onlyconnecting to trusted nodes, do not seed via DNS, or listen by default
if(gArgs.SoftSetBoolArg("-dnsseed", false))
LogPrintf("%s: parameter interaction: -connect set -> setting-dnsseed=0\n", __func__);
if (gArgs.SoftSetBoolArg("-listen",false))
LogPrintf("%s: parameter interaction: -connect set -> setting-listen=0\n", __func__);
}
判断gArgs中,是否包含-connect参数,如果包括,切没用绑定地址,则将-dnsseed与-listen设置为0,如果绑定了地址,则listen仍为1.这一点后续有详细说明。
3)代理模式
if(gArgs.IsArgSet("-proxy")) {
// to protectprivacy, do not listen by default if a default proxy server is specified
if(gArgs.SoftSetBoolArg("-listen", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting-listen=0\n", __func__);
// to protect privacy, do not use UPNPwhen a proxy is set. The user may still specify -listen=1
// to listenlocally, so don't rely on this happening through -listen below.
if(gArgs.SoftSetBoolArg("-upnp", false))
LogPrintf("%s:parameter interaction: -proxy set -> setting -upnp=0\n", __func__);
// to protectprivacy, do not discover addresses by default
if(gArgs.SoftSetBoolArg("-discover", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting-discover=0\n", __func__);
}
这是设置代理参数,目的是保护隐私,如果设置了设置了代理模式,-listen,upnp,以及discover均设置为false,即比特币后台进程只使用代理提供的监听地址与端口,并且不去查找默认的监听地址,这里upnp代表的意思是使用全局即插即用(upnp)映射监听端口,默认不使用。
4)监听设置处理
if(!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
// do not map ports or try to retrievepublic IP when not listening (pointless)
if(gArgs.SoftSetBoolArg("-upnp", false))
LogPrintf("%s: parameter interaction: -listen=0 -> setting-upnp=0\n", __func__);
if(gArgs.SoftSetBoolArg("-discover", false))
LogPrintf("%s: parameter interaction: -listen=0 -> setting-discover=0\n", __func__);
if(gArgs.SoftSetBoolArg("-listenonion", false))
LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n",__func__);
}
监听处理,DEFAULT_LISTEN默认为true。如果监听设置为false,即不实施监听,则端口upnp,discover,listenonion均设置为false。Listenonion匿名地址监听,此处涉及通信机制的一个概念,第二代洋葱路由(onion routing),其解释如下:
Tor(The Onion Router)是第二代洋葱路由(onion routing)的一种实现,用户通过Tor可以在因特网上进行匿名交流。Tor专门防范流量过滤、嗅探分析,让用户免受其害。最初该项目由美国海军研究实验室赞助。2004年后期,Tor成为电子前哨基金会的一个项目。2005年后期,EFF不再赞助Tor项目,但他们继续维持Tor的官方网站。
5)外部IP处理
if(gArgs.IsArgSet("-externalip")) {
// if anexplicit public IP is specified, do not try to find others
if(gArgs.SoftSetBoolArg("-discover", false))
LogPrintf("%s: parameter interaction: -externalip set -> setting-discover=0\n", __func__);
}
如果设置了外部的IP地址,那么bitcoind就不需要在找其他的监听地址了
6)区块模式参数处理
// disablewhitelistrelay in blocksonly mode
if (gArgs.GetBoolArg("-blocksonly",DEFAULT_BLOCKSONLY)) {
if(gArgs.SoftSetBoolArg("-whitelistrelay", false))
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting-whitelistrelay=0\n", __func__);
}
DEFAULT_BLOCKSONLY默认false,设置了区块模式以后,白名单参数whitelistrelay设置为false,即,区块模式下,白名单列表失效。
blocksonly参数为比特币客户端以调试状态启动时才会使用的,这点我们可以从src/init.cp的HelpMessage函数中获取到其帮助信息:
if (showDebug)
strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whetherto operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY));
此处的默认参数DEFAULT_BLOCKSONLY在src/net.h中定义,具体定义如下:
/** Default for blocks only*/
static const bool DEFAULT_BLOCKSONLY =false;
我们可以看到其默认条件下为false,即默认不会只以区块模式运行,因为如果在区块模式下运行,全网的交易将不会被打包,钱包的交易广播功能将失效,也就是我们看到的walletbroadcast参数此时需要设置为false,否则将会互斥。
7)白名单节点参数处理
// Forcing relayfrom whitelisted hosts implies we will accept relays from them in the firstplace.
if(gArgs.GetBoolArg("-whitelistforcerelay",DEFAULT_WHITELISTFORCERELAY)) {
if(gArgs.SoftSetBoolArg("-whitelistrelay", true))
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 ->setting -whitelistrelay=1\n", __func__);
}
}
DEFAULT_WHITELISTFORCERELAY默认true,如果设置了whitelistforcerelay参数,则whitelistrelay为true,表示优先处理白名单节点。
下面分析,如果绑定了地址,即使设置了-connect和proxy参数,程序也会监听这个地址。
从代码分析来看,“表面上“设置了blind以后,listen=true,
if (gArgs.IsArgSet("-bind")) {
if(gArgs.SoftSetBoolArg("-listen", true))
LogPrintf("%s: parameter interaction: -bind set -> setting-listen=1\n", __func__);
}
但后面如果设置了connect,又会把listen设置为false
if(gArgs.IsArgSet("-connect")) {
// when onlyconnecting to trusted nodes, do not seed via DNS, or listen by default
if(gArgs.SoftSetBoolArg("-dnsseed", false))
LogPrintf("%s: parameter interaction: -connect set -> setting-dnsseed=0\n", __func__);
if (gArgs.SoftSetBoolArg("-listen",false))
LogPrintf("%s: parameter interaction: -connect set -> setting-listen=0\n", __func__);
}
但实际情况是这样吗?
下面我们着重分析以下,这也是困惑我的地方。
假设没用blind,只是设置了connect。那么
Bind不执行,whitebind不执行,执行到if(gArgs.IsArgSet("-connect"))以后,执行if(gArgs.SoftSetBoolArg("-listen", false))
我们进入SoftSetBoolArg函数
bool ArgsManager::SoftSetBoolArg(conststd::string& strArg, bool fValue)
{
if (fValue)
return SoftSetArg(strArg, std::string("1"));
else
return SoftSetArg(strArg, std::string("0"));
}
strArg=listen,fValue=0,因此,会执行else语句,下面进入函数SoftSetArg:
bool ArgsManager::SoftSetArg(conststd::string& strArg, const std::string& strValue)
{
LOCK(cs_args);
if (IsArgSet(strArg)) return false;
ForceSetArg(strArg, strValue);
return true;
}
strArg=listen, strValue为0,函数判断是否有listen,如果有,则返回false,如果没有,则设置一个参数listen,并设置参数值为false,然后返回一个true。我们在此已经设置了listen,因此直接返回false。因此SoftSetBoolArg函数返回的也是false,listen设置为false
如果设置了bind,则listen=true,当执行-connet 语句中的if (gArgs.SoftSetBoolArg("-listen",
false))时, SoftSetBoolArg的传入函数是listen,和false,因此执行SoftSetArg(strArg,std::string("0"));
在SoftSetArg函数中,因为设置了listen,所以,运行代码if (IsArgSet(strArg)) return
false时,直接返回false,不会将listen设置为0,并且不会打印消息
之所以认为设置了-connect以后,就会把listen设置为false,是因为自己对SoftSetBoolArg函数理解不透。
至此,我们把函数InitParameterInteraction()分析完了。
区块链研习社比特币源码研读班 electroman
以下是广告:
我们区块链研习社已创建“区块链研习社币圈交流”小密圈”,在小密圈中,我们将带领大家一起学习区块链的原理与投资,还将提供区块链基本原理解答、交易所注册与交易操作、ICO交易与操作、投资分析、风险分析等内容。