美文网首页区块链研习社
比特币源码研读(11)-main函数

比特币源码研读(11)-main函数

作者: electroman | 来源:发表于2017-11-26 15:21 被阅读115次

    上次,我们分析了比特币的日志信息打印。今天我们继续分析下面的代码。

    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交易与操作、投资分析、风险分析等内容。

    相关文章

      网友评论

        本文标题:比特币源码研读(11)-main函数

        本文链接:https://www.haomeiwen.com/subject/zabkbxtx.html