比特币源码研读11-程序入口函数解析(10)

这篇已经是源码研读的第十一篇了,一路走来,并不容易,因为比较枯燥,难度也不小,放弃之心时不时便涌上心头。相信我,你并不孤独,你遇到过的问题,前人早有经历,细想下,把基础打好,后面的路就好走的多了。就好像学车一样,一开始的学方向盘,练离合刹车油门,挂挡,你很可能会不耐烦,觉得太简单了,便心不在焉,不放在心上。But, 一旦如此,后面就要在这些简单事情上摔跟头,然后不得不重新回头学起。倒不如一开始就将基本功打好了,后面不仅能少挨教练骂,学起其他项目也会更得心应手。

好了,言归正传,接着上一篇继续分析函数AppInitParameterInteraction剩下的代码。

一、交易池大小限定参数

以下代码中,首先得到mempool的最大值,然后将max mempool参数值乘以 1000000,将单位有 MB 换成 B,最后计算 mempool 的最小值,乘以1000是将单位从 KB转为 B,乘以40代表最小可以容纳40个交易族。

// mempool limits

    int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;

    int64_t nMempoolSizeMin = 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)));

其中,默认最大交易池常量 DEFAULT_MAX_MEMPOOL_SIZE 定义在policy.h,值为300Mb。

默认最小的交易池常量 DEFAULT_DESCENDANT_SIZE_LIMIT, 101 kb.

/** Default for -maxmempool, maximum megabytes of mempool memory usage */ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;

/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */

static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;

二、交易费增长量

incremental relay fee,即交易费增长量。这里设置的最低费用增长量,主要是为了考虑到交易池的容量限制,取消一些交易费用过低的交易。

// incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool

    // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.

    if (IsArgSet("-incrementalrelayfee"))

    {

        CAmount n = 0;

        if (!ParseMoney(GetArg("-incrementalrelayfee", ""), n))

            return InitError(AmountErrMsg("incrementalrelayfee", GetArg("-incrementalrelayfee", "")));

        incrementalRelayFee = CFeeRate(n);

    }

当mempool 中的交易数量超过阈值,交易费用阈值就会跟着增加,增加量就是由incrementalrelayfee这个变量决定,默认值为1000聪,即0.00001BTC.

默认值 DEFAULT_INCREMENTAL_RELAY_FEE 同样定义于 policy.h:

/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP 125 replacement **/

static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 1000;

三、检查脚本线程数

参数-par=0 意味着程序根据机器情况自动检测线程数但同时nScriptCheckThreads==0意味着不使用并发。

// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency

    nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);

    if (nScriptCheckThreads <= 0)

        nScriptCheckThreads += GetNumCores();

    if (nScriptCheckThreads <= 1)

        nScriptCheckThreads = 0;

    else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)

        nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;

定义于validation.h的默认的脚本检查线程数变量值为0, 即程序默认使用自动检测。

/** -par default (number of script-checking threads, 0 = auto) */

static const int DEFAULT_SCRIPTCHECK_THREADS = 0;

还有最大的脚本检查线程数变量值为16,即程序最多启用16个线程对脚本进行检查。


/** Maximum number of script-checking threads allowed */

static const int MAX_SCRIPTCHECK_THREADS = 16;

函数GetNumCores()定义于util.cpp,其中,physical_concurrency()函数返回当前系统的物理内核数量,跟hardware_concurrency()不同,它并不把虚拟内核算进去。

但当BOOST版本小于105600,就得使用hardware_concurrency()代替。


int GetNumCores()

{

#if BOOST_VERSION >= 105600

    return boost::thread::physical_concurrency();

#else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores

    return boost::thread::hardware_concurrency();

#endif

}

四、区块修剪

注释:区块修剪,通过获得当前磁盘空间的大小来分配区块和删除文件.

首先参数"-prune"不能为负数否则报错并退出程序该参数在前面的文章中也说过,其取值有以下三种:

0: 禁止修剪

1: 手动修剪,通过RPC调用pruneblockchain(height) 函数删除旧区块文件

大于等于 550M表示存储区块和 undo 文件的大小至于这个550M哪里来的,下面自有详解。

// block pruning; get the amount of disk space (in MiB) to allot for block & undo files

int64_t nPruneArg = GetArg("-prune", 0);

if (nPruneArg < 0) {

return InitError(_("Prune cannot be configured with a negative value."));

}

nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024; //将nPruneArg转为字节数

if (nPruneArg == 1) {// manual pruning: -prune=1 

LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");

nPruneTarget = std::numeric_limits::max();

        fPruneMode = true;

} else if (nPruneTarget) {

        if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {

            return InitError(strprintf(_("Prune configured below the minimum of %d MiB.  Please use a higher number."),

MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));

        }

        LogPrintf("Prune configured to target %uMiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);

        fPruneMode = true;

    }

其中,validation.h 中的全局变量 MIN_DISK_SPACE_FOR_BLOCK_FILES 为 550M。从注释中可以看出,机器至少需要550M空间来存储区块和 undo 文件。所以为了能让程序正常运行,需要将"-prune"的值设置大于550才行。fPruneMode = true;将修剪模式打开,这将会在后面的程序对区块进行具体修剪的操作中用到。

// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)

// At 1MB per block, 288 blocks = 288MB.

// Add 15% for Undo data = 331MB

// Add 20% for Orphan block rate = 397MB

// We want the low water mark after pruning to be at least 397 MB and since we prune in

// full block file chunks, we need the high water mark which triggers the prune to be

// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB

// Setting the target to > than 550MB will make it likely we can respect the target.

static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;

今天到此为止,下次继续讲解RPC命令注册函数。敬请期待。

区块链研习社源码研读班 Jacky

你可能感兴趣的:(比特币源码研读11-程序入口函数解析(10))