比特幣源碼研讀之三

接下來我們來看下一些程序初始化設(shè)置的一些操作,主要涉及的文件:

bitcoind.cpp、init.cpp、util.cpp

首先是InitLogging(), 設(shè)置日志相關(guān)的參數(shù), 默認(rèn)日志存儲(chǔ)在$DataDir/debug.log

void InitLogging()
{
    //是否打印日志到console終端
    fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", false);
    //是否記錄時(shí)間戳到日志中
    fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
    //是否記錄微秒至日志中
    fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
    //是否記錄IP至日志中
    fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);

    LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    //打印版本詳細(xì)信息
    LogPrintf("Bitcoin version %s\n", FormatFullVersion());
}

InitParameterInteraction()是處理網(wǎng)絡(luò)連接相關(guān)的參數(shù)設(shè)置,具體可參考:http://www.itdecent.cn/p/811c0c01eedb

AppInitBasicSetup()程序初始化的一些與系統(tǒng)相關(guān)的基本設(shè)置, 請(qǐng)參考:http://www.itdecent.cn/p/d42558e7e8e8

接下來主要分析一下函數(shù)AppInitParameterInteraction()的內(nèi)容。

// if using block pruning, then disallow txindex
    if (gArgs.GetArg("-prune", 0)) {
        if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
            return InitError(_("Prune mode is incompatible with -txindex."));
}

-prune與-txindex是互斥的兩個(gè)參數(shù),即最多只能設(shè)置其中一個(gè)參數(shù)。因?yàn)閜rune參數(shù)是為了節(jié)省區(qū)塊存儲(chǔ)空間而對(duì)區(qū)塊進(jìn)行修剪,不保留無(wú)用數(shù)據(jù)。而txindex是需要維護(hù)整個(gè)區(qū)塊鏈網(wǎng)絡(luò)中所有交易的全索引。

接著將根據(jù)提供的啟動(dòng)參數(shù)-debug以及-debugexclude設(shè)置log記錄的類別。

if (gArgs.IsArgSet("-debug")) {
        // Special-case: if -debug=0/-nodebug is set, turn off debugging messages
        const std::vector<std::string> categories = gArgs.GetArgs("-debug");

        if (find(categories.begin(), categories.end(), std::string("0")) == categories.end()) {//如果沒有設(shè)置-debug=0或-nodebug,則遍歷提供的-debug參數(shù)值
            for (const auto& cat : categories) {
                uint32_t flag = 0;
                if (!GetLogCategory(&flag, &cat)) {//查詢?nèi)罩绢悇e是否存在
                    InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
                    continue;
                }
             logCategories |= flag;//記錄哪個(gè)日志種類的日志需要被記錄,每個(gè)日志種類標(biāo)識(shí)占1bit
            }
        }
}

方法GetLogCategory()將根據(jù)提供的debug參數(shù)值str在數(shù)組LogCategories中搜索,如果存在返回true(同時(shí)將該日志類別對(duì)應(yīng)的編號(hào)f返回),否則返回false。我們來看下GetLogCategory是如何查找相關(guān)的日志類別的:

bool GetLogCategory(uint32_t *f, const std::string *str)
{
    if (f && str) {
        if (*str == "") {
            *f = BCLog::ALL;
            return true;
        }
        for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
            if (LogCategories[i].category == *str) {
                *f = LogCategories[i].flag;
                return true;
            }
        }
    }
    return false;
}

我們來看一下LogCategories的定義,它是一個(gè)CLogCategoryDesc數(shù)組,CLogCategoryDesc類型的由兩個(gè)參數(shù),第一個(gè)為以2的指數(shù)計(jì)算的標(biāo)志位,這么設(shè)計(jì)的原因是方便通過移位運(yùn)算記錄哪些類別的日志需要記錄;第二個(gè)為日志種類。

const CLogCategoryDesc LogCategories[] =
{
    {BCLog::NONE, "0"},
    {BCLog::NET, "net"},
    {BCLog::TOR, "tor"},
    {BCLog::MEMPOOL, "mempool"},
    {BCLog::HTTP, "http"},
    {BCLog::BENCH, "bench"},
    {BCLog::ZMQ, "zmq"},
    {BCLog::DB, "db"},
    {BCLog::RPC, "rpc"},
    {BCLog::ESTIMATEFEE, "estimatefee"},
    {BCLog::ADDRMAN, "addrman"},
    {BCLog::SELECTCOINS, "selectcoins"},
    {BCLog::REINDEX, "reindex"},
    {BCLog::CMPCTBLOCK, "cmpctblock"},
    {BCLog::RAND, "rand"},
    {BCLog::PRUNE, "prune"},
    {BCLog::PROXY, "proxy"},
    {BCLog::MEMPOOLREJ, "mempoolrej"},
    {BCLog::LIBEVENT, "libevent"},
    {BCLog::COINDB, "coindb"},
    {BCLog::QT, "qt"},
    {BCLog::LEVELDB, "leveldb"},
    {BCLog::ALL, "1"},
    {BCLog::ALL, "all"},
};
namespace BCLog {
    enum LogFlags : uint32_t {
        NONE        = 0,
        NET         = (1 <<  0),
        TOR         = (1 <<  1),
        MEMPOOL     = (1 <<  2),
        HTTP        = (1 <<  3),
        BENCH       = (1 <<  4),
        ZMQ         = (1 <<  5),
        DB          = (1 <<  6),
        RPC         = (1 <<  7),
        ESTIMATEFEE = (1 <<  8),
        ADDRMAN     = (1 <<  9),
        SELECTCOINS = (1 << 10),
        REINDEX     = (1 << 11),
        CMPCTBLOCK  = (1 << 12),
        RAND        = (1 << 13),
        PRUNE       = (1 << 14),
        PROXY       = (1 << 15),
        MEMPOOLREJ  = (1 << 16),
        LIBEVENT    = (1 << 17),
        COINDB      = (1 << 18),
        QT          = (1 << 19),
        LEVELDB     = (1 << 20),
        ALL         = ~(uint32_t)0,
    };
}    

接下來參數(shù)-debugexclude正好與-debug參數(shù)相反,用于設(shè)置不需要記錄哪些類別的日志,可以看到在計(jì)算logCategories用的操作符是先對(duì)標(biāo)志位求“反“再求“與”,目的就是把logCategories對(duì)應(yīng)的標(biāo)志位置為0.

// Now remove the logging categories which were explicitly excluded
    for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
        uint32_t flag = 0;
        if (!GetLogCategory(&flag, &cat)) {
            InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
            continue;
        }
        logCategories &= ~flag;
}

接下來是檢查一些過時(shí)的參數(shù)設(shè)置,并予以提示。

    // Check for -debugnet
    if (gArgs.GetBoolArg("-debugnet", false))
        InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net."));
    // Check for -socks - as this is a privacy risk to continue, exit here
    if (gArgs.IsArgSet("-socks"))
        return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
    // Check for -tor - as this is a privacy risk to continue, exit here
    if (gArgs.GetBoolArg("-tor", false))
        return InitError(_("Unsupported argument -tor found, use -onion."));

    if (gArgs.GetBoolArg("-benchmark", false))
        InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench."));

    if (gArgs.GetBoolArg("-whitelistalwaysrelay", false))
        InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay."));

    if (gArgs.IsArgSet("-blockminsize"))
        InitWarning("Unsupported argument -blockminsize ignored.");

接下來是交易池檢查(-checkmempool)、塊index(-checkblockindex)以及檢查點(diǎn)(-checkpoints)參數(shù)的相關(guān)設(shè)置。-checkmempool參數(shù)指定交易池檢查的頻率,-checkblockindex表示是否需要對(duì)塊的索引進(jìn)行檢測(cè),-checkpoints是為了防止節(jié)點(diǎn)接受最后一個(gè)檢查點(diǎn)前的fork鏈,在一定程度上保證了區(qū)塊鏈的安全性。

    int ratio = std::min<int>(std::max<int>(gArgs.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
    if (ratio != 0) {
        mempool.setSanityCheck(1.0 / ratio);
    }
    fCheckBlockIndex = gArgs.GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
    fCheckpointsEnabled = gArgs.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);

下面的兩個(gè)參數(shù)是與交易池容量相關(guān)的,其中-maxmempool用于設(shè)置交易池容量的最大值(注意單位是兆M),另外一個(gè)參數(shù)是- limitdescendantsize,從其英文注釋Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants,可以看出如果某個(gè)交易的任何一個(gè)父交易的所有子交易在mempool中的大小總和大于了該參數(shù)的值(注意單位,不懂為何默認(rèn)值DEFAULT_DESCENDANT_SIZE_LIMIT設(shè)置為101,后面又乘以1000*40??),則不接受該交易,具體原因我們等分析到該參數(shù)的具體實(shí)際使用時(shí)再來分析。

// mempool limits
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
    int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
    if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin)
        return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0)));

好了,本篇就先分析到這。很多內(nèi)容菜菜子(http://www.itdecent.cn/u/30081a05cf95)分析的很詳細(xì),對(duì)我的理解幫助也很大。有些內(nèi)容目前僅僅是按照自己的理解寫出來的,難免與實(shí)際的作用會(huì)有一些出路,我們隨著源碼分析的不斷深入,必將回過頭了驗(yàn)證與糾正我們前面的分析。

因本人水平有限,如有問題,歡迎大家批評(píng)指出,非常感謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 區(qū)塊鏈研習(xí)社比特幣源碼研讀班今天研讀第四步,AppInit初始化 一總體結(jié)構(gòu)圖 二AppInit函數(shù)
    劍有偏鋒閱讀 323評(píng)論 0 0
  • 一、快速術(shù)語(yǔ)檢索 比特幣地址:(例如:1DSrfJdB2AnWaFNgSbv3MZC2m74996JafV)由一串...
    不如假如閱讀 16,566評(píng)論 4 87
  • 本文將繼續(xù)接著上一篇文章繼續(xù)開展源碼研讀之旅,本文將完成初始化基本環(huán)境構(gòu)建源碼部分(AppInitBasicSet...
    菜菜子_forest閱讀 2,169評(píng)論 7 2
  • 世間最大的偽善,莫過于不顧一切的“我為你好”! 如果你不是對(duì)他有所期望,還會(huì)這么失望嗎?” 對(duì)啊,如果不是我覺得他...
    l小南閱讀 441評(píng)論 1 2
  • 畢竟身為一個(gè)東北人過年看不到本山大叔還是有點(diǎn)孤單寂寞~再加上下班想著放輕松看個(gè)傻白甜的電影,無(wú)視豆瓣的2星半的評(píng)價(jià)...
    憂郁的松餅閱讀 983評(píng)論 0 1

友情鏈接更多精彩內(nèi)容