比特幣源碼研讀之六

本文將繼續(xù)參數(shù)處理其他部分源碼的研讀。

本文主要涉及的源碼文件包括:

src/bitcond.cpp、src/util.h、src/util.cpp、src/init.h、src/init.cpp、src/chainparamsbase.h、src/chainparamsbase.cpp、src/chainparams.h、src/chainparams.cpp

一、比特幣網(wǎng)絡(luò)

比特幣網(wǎng)絡(luò)分為主網(wǎng)、測試網(wǎng)以及私有網(wǎng)三種網(wǎng)絡(luò),其中主網(wǎng)就是我們現(xiàn)在使用的正式運(yùn)行的可進(jìn)行實(shí)際交易的網(wǎng)絡(luò),在其上我們可以實(shí)現(xiàn)物品的交易與服務(wù);測試網(wǎng)顧名思義即為公共測試網(wǎng)絡(luò),因?yàn)槠鋵?shí)測試網(wǎng),所以,其上的信息是可以重設(shè)的;私有網(wǎng)的難度很低,很容易產(chǎn)生塊,所以開發(fā)者一般在私有網(wǎng)中開展應(yīng)用的開發(fā)與自測試。三個(gè)網(wǎng)絡(luò)的的英文名分別為:

主網(wǎng):Main network

測試網(wǎng):Testnet (v3)

私有網(wǎng):Regression test

二、選擇比特幣網(wǎng)絡(luò)

介紹完比特幣網(wǎng)絡(luò)的三種類型后,我們來看如下代碼:

//Check for -testnet or -regtest parameter (Params() calls are only valid afterthis clause)

try{

SelectParams(ChainNameFromCommandLine());

} catch (const std::exception&e) {

fprintf(stderr,"Error: %s\n", e.what());

returnfalse;

}

首先我們來看代碼注釋,其注釋的含義為檢測-testnet或者-regtest參數(shù)。那么這兩個(gè)參數(shù)是什么意思呢?它們分別是我們前面介紹的測試網(wǎng)和私有網(wǎng)。

知道了后面代碼的具體功能后,我們就繼續(xù)對代碼進(jìn)行深入剖析。注釋后面的代碼通過try catch異常捕捉機(jī)制實(shí)現(xiàn)比特幣網(wǎng)絡(luò)設(shè)置工作。在try代碼塊中,SelectParams函數(shù)以ChainNameFromCommandLine()返回值作為參數(shù),SelectParams函數(shù)的聲明位于src/chainparams.h中,其參數(shù)為字符串類型。那ChainNameFromCommandLine()的返回值是什么呢?

(1)獲取網(wǎng)絡(luò)名稱

要知道ChainNameFromCommandLine()的返回值需進(jìn)入src/chainparamsbase.cpp一看究竟。其函數(shù)實(shí)現(xiàn)如下:

std::string ChainNameFromCommandLine()

{

boolfRegTest = GetBoolArg("-regtest", false);

boolfTestNet = GetBoolArg("-testnet", false);

if(fTestNet && fRegTest)

throwstd::runtime_error("Invalid combination of -regtest and -testnet.");

if(fRegTest)

returnCBaseChainParams::REGTEST;

if(fTestNet)

returnCBaseChainParams::TESTNET;

returnCBaseChainParams::MAIN;

}

ChainNameFromCommandLine()函數(shù)從其名稱可以看出,該函數(shù)將從命令行中獲取鏈路的名稱。其實(shí)現(xiàn)流程如圖所示。

1)該函數(shù)首先獲取"-regtest"與"-testnet"參數(shù)設(shè)置情況;

2)如果兩個(gè)參數(shù)都設(shè)置了,因?yàn)橐粋€(gè)比特幣程序不可能同時(shí)存在兩個(gè)網(wǎng)絡(luò),所以,程序?qū)惓M顺?,同時(shí)拋出異常錯(cuò)誤,由之前的try catch模塊處理,打印異常錯(cuò)誤提示信息;

3)如果只設(shè)置了回歸測試,則返回CBaseChainParams::REGTEST,REGTEST為靜態(tài)字符串常量,代表的是回歸測試,與其并行的另兩個(gè)網(wǎng)絡(luò)描述字符串也為靜態(tài)字符串常量,他們均在src/chainparamsbase.h中聲明,也同時(shí)在src/chainparamsbase.cpp中定義。其聲明與定義如下:

聲明:

定義:

const std::string CBaseChainParams::MAIN = "main"; //主網(wǎng)

const std::string CBaseChainParams::TESTNET = "test"; //測試網(wǎng)

const std::string CBaseChainParams::REGTEST = "regtest"; //私有網(wǎng)

4)如果只設(shè)置了測試網(wǎng)絡(luò),,則返回CBaseChainParams::TESTNET;

5)如果都沒有設(shè)置,則返回,則返回CBaseChainParams::MAIN。

(2)網(wǎng)絡(luò)基本參數(shù)設(shè)置

在獲得網(wǎng)絡(luò)名稱后,我們將其傳給SelectParams函數(shù),該函數(shù)的實(shí)現(xiàn)位于chainparams.cpp中,其函數(shù)實(shí)現(xiàn)如下:

void SelectParams(conststd::string& network)

{

SelectBaseParams(network);

pCurrentParams = &Params(network);

}

在該函數(shù)中首先調(diào)用SelectBaseParams函數(shù),該函數(shù)的實(shí)現(xiàn)位于chainparamsbase.cpp中,其函數(shù)實(shí)現(xiàn)內(nèi)容如下:

void SelectBaseParams(conststd::string& chain)

{

pCurrentBaseParams = &BaseParams(chain);

}

在該函數(shù)中,實(shí)現(xiàn)了對鏈參數(shù)對象pCurrentBaseParams的賦值,pCurrentBaseParams的類型為CBaseChainParams指針,其定義位于src/chainparams.cpp中,從定義可以看出pCurrentBaseParams為靜態(tài)全局變量。

static CBaseChainParams* pCurrentBaseParams = 0;

CBaseChainParams類為前面提到的3種區(qū)塊鏈基本參數(shù)的基類,3種區(qū)塊鏈基本參數(shù)設(shè)置類分別為:CBaseMainParams、CBaseTestNetParams、CBaseRegTestParams,其定義位于src/chainparamsbase.cpp中,具體定義代碼如下:

/**

*Main network主網(wǎng)

*/

class CBaseMainParams : publicCBaseChainParams

{

public:

CBaseMainParams()

{

nRPCPort = 8332;

}

};

static CBaseMainParams mainParams;

/**

*Testnet (v3)測試網(wǎng)

*/

class CBaseTestNetParams : publicCBaseChainParams

{

public:

CBaseTestNetParams()

{

nRPCPort = 18332;

strDataDir = "testnet3";

}

};

static CBaseTestNetParams testNetParams;

/*

*Regression test私有鏈

*/

class CBaseRegTestParams : publicCBaseChainParams

{

public:

CBaseRegTestParams()

{

nRPCPort = 18332;

strDataDir = "regtest";

}

};

static CBaseRegTestParams regTestParams;

從上述定義我們可以看到每個(gè)類的構(gòu)造函數(shù)中定義了主鏈、測試鏈以及私有鏈?zhǔn)褂玫亩丝谂c數(shù)據(jù)目錄,其端口分別為8332、18332以及18332。

在完成3種鏈的定義后,我們再來看BaseParams函數(shù)的實(shí)現(xiàn)就很容易明白其返回值的意義了:

CBaseChainParams& BaseParams(conststd::string& chain)

{

if (chain == CBaseChainParams::MAIN)

return mainParams;

else if (chain == CBaseChainParams::TESTNET)

return testNetParams;

else if (chain == CBaseChainParams::REGTEST)

return regTestParams;

else

throw std::runtime_error(strprintf("%s: Unknown chain %s.",__func__, chain));

}

BaseParams將返回對應(yīng)鏈的基本參數(shù)對象,并賦值給pCurrentBaseParams。

3)主要參數(shù)設(shè)置

我們最后再來看SelectParams中的pCurrentParams = &Params(network);代碼。其實(shí)現(xiàn)與我們剛看到的BaseParams有點(diǎn)類似,只不過其少了Base單詞而已,我們可以這樣理解,在執(zhí)行完鏈的基本參數(shù)設(shè)置后,比特幣程序?qū)⒃O(shè)置相應(yīng)鏈的主要參數(shù)了。從Params函數(shù)實(shí)現(xiàn)我們可以看到,其實(shí)現(xiàn)與BaseParams是一樣的,都是根據(jù)鏈名稱獲取相應(yīng)的鏈參數(shù)對象,只不過此處的鏈路參數(shù)類中包含的參數(shù)信息更詳細(xì)些。主鏈、測試鏈以及私有鏈對應(yīng)的類分別為CMainParams、CTestNetParams、CRegTestParamsstatic,這3個(gè)類的定義位于src/chainparams.cpp中,它們均繼承了CChainParams類,通過CChainParams可知鏈參數(shù)類主要實(shí)現(xiàn)共識(shí)參數(shù)、CDNSSeedData種子數(shù)據(jù)、默認(rèn)端口、創(chuàng)世塊信息以及鏈交易數(shù)據(jù)等參數(shù)的設(shè)置。

這里要著重講解的是共識(shí)參數(shù)與創(chuàng)世塊信息參數(shù),它們分別為:

Consensus::Params consensus;

CBlock genesis;

因?yàn)槲覀冎饕褂弥骶W(wǎng),因此以主網(wǎng)中的參數(shù)內(nèi)容來說明我們經(jīng)常聽到的區(qū)塊獎(jiǎng)勵(lì)減半、出塊時(shí)間、創(chuàng)世塊獎(jiǎng)勵(lì)等參數(shù)是如何設(shè)置的。

區(qū)塊獎(jiǎng)勵(lì)減半間隔:consensus.nSubsidyHalvingInterval = 210000;

算力極限值:consensus.powLimit =uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");

算力修改間隔:consensus.nPowTargetSpacing = 10 * 60;即10分鐘

創(chuàng)世塊genesis = CreateGenesisBlock(1231006505, 2083236893,0x1d00ffff, 1, 50 * COIN);第一個(gè)塊的獎(jiǎng)勵(lì)為50個(gè)比特幣

以上這些參數(shù)都是我們經(jīng)常聽到的名詞,如果我們想創(chuàng)建自己命名的數(shù)字貨幣,只需簡單修改這些參數(shù)即可,比如把區(qū)塊獎(jiǎng)勵(lì)減半間隔修改為420000或其他數(shù),創(chuàng)世塊中比特幣獎(jiǎng)勵(lì)的50該為100或其他數(shù)。所以要?jiǎng)?chuàng)建一個(gè)自己的數(shù)字貨幣并不難,關(guān)鍵在于看其是否有應(yīng)用價(jià)值。

程序在每個(gè)類的定義之后,程序也定義了對應(yīng)的靜態(tài)鏈參數(shù)對象。

static CMainParamsmainParams;

staticCTestNetParams testNetParams;

staticCRegTestParams regTestParams;

Params將根據(jù)用戶設(shè)置的鏈參數(shù)名稱,將對應(yīng)的鏈參數(shù)返回給pCurrentParams,從而完成鏈基本參數(shù)與主要參數(shù)的實(shí)現(xiàn)任務(wù)。

至此,程序根據(jù)用戶輸入的網(wǎng)絡(luò)類型參數(shù)完成了比特幣運(yùn)行網(wǎng)絡(luò)的設(shè)置。在這段代碼中,我知道了私有網(wǎng)絡(luò),以前聽得最多的是主網(wǎng)和測試網(wǎng),而私有網(wǎng)或私有鏈基本很少聽到,在這段代碼中我知道了私有鏈?zhǔn)情_發(fā)團(tuán)隊(duì)在開發(fā)時(shí)使用的網(wǎng)絡(luò),因?yàn)槠渫诘V難度很低,很容易進(jìn)行程序的調(diào)試與功能試驗(yàn)。進(jìn)而讓我明白了一些區(qū)塊鏈項(xiàng)目為什么會(huì)說在XX時(shí)刻要進(jìn)入測試網(wǎng)階段,然后再是最終的主網(wǎng)運(yùn)行階段。因此區(qū)塊鏈開發(fā)過程應(yīng)該是這樣的:

以上就是本文的源碼研讀過程,通過源碼的研讀確實(shí)讓我更好地理解區(qū)塊鏈網(wǎng)絡(luò)的運(yùn)轉(zhuǎn)過程,也讓我清晰地明白市場上每個(gè)區(qū)塊鏈的具體進(jìn)程,這樣可以讓我更好地判斷每個(gè)區(qū)塊鏈產(chǎn)品的價(jià)值,對我投資區(qū)塊鏈資產(chǎn)也有很大的幫助。

我是區(qū)塊鏈研習(xí)社的菜菜子,我將繼續(xù)深入研究比特幣源碼,源碼研讀系列也將繼續(xù)更新,敬請期待!

作者:區(qū)塊鏈研習(xí)社比特幣源碼研讀班 菜菜子


以下是廣告:

我們區(qū)塊鏈研習(xí)社已創(chuàng)建“區(qū)塊鏈研習(xí)社幣圈交流”小密圈”,在小密圈中,我們將帶領(lǐng)大家一起學(xué)習(xí)區(qū)塊鏈的原理與投資,還將提供區(qū)塊鏈基本原理解答、交易所注冊與交易操作、ICO交易與操作、投資分析、風(fēng)險(xiǎn)分析等內(nèi)容。

目前入圈價(jià)格初始定價(jià)50元,50人調(diào)整一次價(jià)格,每次調(diào)整幅度為50元!

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

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

  • 原文地址 https://mbinary.coding.me/introduction-to-bitcoin.ht...
    mbinary閱讀 5,728評論 0 4
  • 以前,我經(jīng)常聽人說:“好孩子是夸出來的”,我不愿茍同,頗有微詞。但最近的一件事讓我徹底改變了看法。 ...
    7710b5521df3閱讀 282評論 0 3
  • 周二,國慶節(jié),家。 天氣晴。 1.有時(shí)候愛一個(gè)人,就是把無聊的事情拿出來跟她分享。 你會(huì)發(fā)現(xiàn),明明很無聊的一件事,...
    蘑菇菌閱讀 111評論 0 1
  • 【標(biāo) 題】短暫之旅,烙印之深 【作 者】烈焰二連 迷谷 【正文字?jǐn)?shù)】1389 同一個(gè)剽悍,不同的你我,...
    zhen_5ac6閱讀 221評論 0 0
  • 1月12日,晴,忙暈。 閱讀書目:《日本的八個(gè)審美意識(shí)》 作者:黑川雅之畢業(yè)于日本著名的早稻田大學(xué),他是日本少有的...
    陳陳_19b4閱讀 791評論 0 3

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