
0x00 為啥要讀
如果說(shuō)是在18年以前閱讀比特幣代碼,是價(jià)值投資的基本操作,那今年再去做這個(gè)事,絕逼是信仰了。比特幣作為虛擬貨幣的開(kāi)山鼻祖,運(yùn)行至今近10年,在沒(méi)有中心化結(jié)構(gòu)的運(yùn)營(yíng)下,幾乎沒(méi)有出現(xiàn)過(guò)重大事故,相信BAT的產(chǎn)品也不敢吹這牛逼吧,所以作為技術(shù)人員讀一讀比特幣代碼是修煉內(nèi)功的絕佳選擇。由于比特幣代碼相比于我們之前所研發(fā)的C(B)/S結(jié)構(gòu)不同,理解起來(lái)總會(huì)有一些吃力,如果能有一群水平差不多的朋友在一起互開(kāi)腦洞,共同勉勵(lì),那更是一件美妙的事情。機(jī)緣巧合認(rèn)識(shí)到國(guó)內(nèi)第一批研讀比特幣代碼的大神@菜菜子,經(jīng)過(guò)幾次溝通,他組織發(fā)起我們共同去做這個(gè)事情,在此特別感謝!
0x01 閱讀思路
按照我以前的習(xí)慣,如果想去學(xué)習(xí)一門(mén)技術(shù),那首先要去學(xué)會(huì)使用這門(mén)技術(shù)。話說(shuō)學(xué)習(xí)使用比特幣成本還是蠻大的,按照今天的行情BTC一枚也要4W多人民幣。不過(guò)沒(méi)有關(guān)系,我們還有很多其他的山寨幣,操作起來(lái)也都是大同小異。利用3個(gè)月的時(shí)間,我從交易所到錢(qián)包,從公鏈到側(cè)鏈,從炒幣到各種DAPP幾乎都玩了一遍。這個(gè)時(shí)候再去學(xué)習(xí)區(qū)塊鏈的技術(shù),知道自己該如何做信息過(guò)濾了,身邊的同仁也會(huì)越來(lái)越多,遇到問(wèn)題的時(shí)候,解決起來(lái)也就得心應(yīng)手了。
在開(kāi)始閱讀代碼之前,《比特幣白皮書(shū)》和《精通比特幣》這兩份材料是必須要讀的,對(duì),必須。即使讀不懂也沒(méi)關(guān)系,至少?gòu)暮暧^上對(duì)比特幣的技術(shù)有個(gè)大致的了解,腦子里有區(qū)塊鏈模糊的樣子,這是很重要的,如果一開(kāi)始就從某個(gè)技術(shù)細(xì)節(jié)入手,比如密碼學(xué),P2P,很容易就走進(jìn)一個(gè)死胡同,最后無(wú)疾而終。

0x02 環(huán)境搭建
工欲善其事,必先利其器。首先我們先選個(gè)版本,我用的是Bitcoin Core Daemon version v0.16.99.0-b1dc39d。在開(kāi)始研讀代碼之前,我們先把環(huán)境搭好。由于常年在Windows下面做開(kāi)發(fā),我嘗試過(guò)搭建bitcoin的windows環(huán)境,網(wǎng)上也能搜索到教程,但我不推薦大家去這么做,因?yàn)檫@是一個(gè)巨坑,詳細(xì)就不多贅述了。我選擇的系統(tǒng)環(huán)境是Ubuntu 14.04 Server LTS,我不太喜歡用桌面版。具體搭建的教程在互聯(lián)網(wǎng)上能搜到@菜菜子的教程,講的很詳細(xì),一步一步做下去就是了。IDE我嘗試過(guò)幾個(gè),sublime,vscode,甚至Idea,我覺(jué)得都不夠好用,最主要的是對(duì)“代碼引用”這個(gè)功能支持的不好,最后只好祭出了江湖殺器Visual Stuio,但VS導(dǎo)入文件夾的功能不是很友好,只好自己先去Create Filter,然后再導(dǎo)入文件。最后我想強(qiáng)調(diào)一點(diǎn)的是關(guān)于代碼的調(diào)試,可能很多朋友喜歡用Log調(diào)試,我個(gè)人還是喜歡debug,我用的是gdb,不過(guò)要注意的是,在make文件之前要修改所有目錄下的makefile,把編譯的優(yōu)化禁止掉,也就是把g++的編譯選項(xiàng)-O2改成-O0,這樣就能跟蹤代碼的完整的執(zhí)行流程了。

0x03 目錄結(jié)構(gòu)&數(shù)據(jù)結(jié)構(gòu)
整個(gè)的項(xiàng)目的目錄結(jié)構(gòu)可以參考下圖(圖片來(lái)源于互聯(lián)網(wǎng))

讀了一下前輩的研讀代碼,基本都是從函數(shù)入口進(jìn)行介紹的,是基于函數(shù)跳轉(zhuǎn)分析的,也就是我們平時(shí)調(diào)試的callstack。我研讀的方式稍有不同,我是從整個(gè)比特幣的數(shù)據(jù)結(jié)構(gòu)入手的。我們都知道比特幣代碼是基于區(qū)塊鏈技術(shù)的,腦子里都有鏈表這樣的一個(gè)概念,一環(huán)一環(huán)利用指針依次連接起來(lái)。如果我們知道每個(gè)節(jié)點(diǎn)里的數(shù)據(jù)結(jié)構(gòu),甚至是內(nèi)存布局,然后再去分析每個(gè)數(shù)據(jù)結(jié)構(gòu)在代碼中扮演的角色,各個(gè)數(shù)據(jù)結(jié)構(gòu)之間的組織方式,是Has-A,還是Is-A,按照這個(gè)思路去閱讀代碼,就輕松愉悅加開(kāi)心了。
首先來(lái)分析chain.h和chain.cpp這兩個(gè)文件,里面包含了這樣的類(lèi)。
CBlockIndex
CDiskBlockIndex
CChain
類(lèi)的關(guān)系成員變量及關(guān)系圖如下:

再來(lái)分析block.h和block.cpp這兩個(gè)文件,里面包含如下幾個(gè)類(lèi)。
CBlockHeader
CBlock
CBlockLocator
類(lèi)的關(guān)系成員變量及關(guān)系圖如下:

從上面的分析可以看出CBlockIndex是Block的內(nèi)存索引,Block的詳細(xì)數(shù)據(jù)是懶加載(lazy-load),只有在使用的時(shí)候才會(huì)用硬盤(pán)數(shù)據(jù)讀取。Block在硬盤(pán)序列化的數(shù)據(jù)除了類(lèi)里的成員變量之外,還有一些額外的數(shù)據(jù)如下圖所示,看到這些是不是很眼熟,在剛開(kāi)始接觸windows PE文件的時(shí)候,思路和這個(gè)也是類(lèi)似的。

有網(wǎng)友總結(jié)出來(lái)的更簡(jiǎn)單粗暴的圖,如下(圖片來(lái)源于互聯(lián)網(wǎng)),這個(gè)圖,我很喜歡,哈哈哈。

0x04 總結(jié)
本開(kāi)篇小節(jié)主要講述了研讀BTC代碼的動(dòng)機(jī)和方法,立Flag去做一件事情可能會(huì)很簡(jiǎn)單,但能堅(jiān)持下來(lái)是一件很不容易的事情,由于本人能力有限,文中有描述不當(dāng)?shù)牡胤?,還請(qǐng)大家多多包涵。下一小節(jié),主要講交易的數(shù)據(jù)結(jié)構(gòu),See u then!
本文由區(qū)塊鏈研習(xí)社源碼研讀班@Hefe原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處!