如何解析 Bitcoin 的數(shù)據(jù)(1)


轉(zhuǎn)自 https://www.arcblock.io/zh/post/2018/08/16/index-bitcoin

如何解析 Bitcoin 數(shù)據(jù)?

眾所周知灭返,互聯(lián)網(wǎng)上的數(shù)據(jù)紛繁復(fù)雜蜓氨,而搜索引擎卻能在海量的數(shù)據(jù)里面迅速的查找出用戶(hù)想要的結(jié)果脆诉。其之所以能夠做到這一點(diǎn)是因?yàn)樗阉饕娴暮竺孢€有兩個(gè)默默付出的組件 -- 爬蟲(chóng)和倒排索引宠纯。 爬蟲(chóng)負(fù)責(zé)不停的從互聯(lián)網(wǎng)上搜集數(shù)據(jù)膊夹,倒排索引負(fù)責(zé)將數(shù)據(jù)以特定的形式存儲(chǔ),以便搜索引擎能夠快速的查詢(xún)昔脯。

Bitcoin 的數(shù)據(jù)都是以二進(jìn)制的形式存在節(jié)點(diǎn)的磁盤(pán)上的啄糙。但是數(shù)據(jù)是以一種對(duì)人不太友好的方式組織在一起的,所以我們首先需要一個(gè)解析器云稚,將這些二進(jìn)制數(shù)據(jù)讀出來(lái)隧饼,還原成它們本來(lái)的面目。之后我們?cè)賹?duì)這些數(shù)據(jù)進(jìn)行一些加工静陈,就得到了 我們所需要的數(shù)據(jù)燕雁。

Bitcoin 數(shù)據(jù)是如何存儲(chǔ)的

存儲(chǔ)數(shù)據(jù)的文件

Bitcoin 的原始數(shù)據(jù)可以在 $HOME/.bitcoin/blocks 下面找到。這個(gè)目錄下面主要有兩類(lèi)文件鲸拥,一種是類(lèi)似于這樣的文件:blk00952.dat拐格, 而另一種是類(lèi)似于這樣的文件:rev000952.dat。 前一種 blk 開(kāi)頭的文件就是存儲(chǔ) Bitcoin 源數(shù)據(jù)的文件刑赶,而后一種是用來(lái)做 rewind 的捏浊。關(guān)于 rewind 我們下回再表,我們這次的重點(diǎn)在源數(shù)據(jù)文件撞叨。每一個(gè) blk 數(shù)據(jù)文件大小的上限都是 128MB金踪。當(dāng)一個(gè)文件寫(xiě)滿(mǎn)后浊洞,Bitcoin 程序會(huì)新建一個(gè)類(lèi)似的文件來(lái)存儲(chǔ)新收到的區(qū)塊信息。

讓我們先通過(guò)如下命令热康,來(lái)看看這些文件里面都存了什么沛申。

od -x --endian=big -N 297 -An blk00000.dat

f9be b4d9 1d01 0000 0100 0000 0000 0000
 0000 0000 0000 0000 0000 0000 0000 0000
 0000 0000 0000 0000 0000 0000 3ba3 edfd
 7a7b 12b2 7ac7 2c3e 6776 8f61 7fc8 1bc3
 888a 5132 3a9f b8aa 4b1e 5e4a 29ab 5f49
 ffff 001d 1dac 2b7c 0101 0000 0001 0000
 0000 0000 0000 0000 0000 0000 0000 0000
 0000 0000 0000 0000 0000 0000 0000 ffff
 ffff 4d04 ffff 001d 0104 4554 6865 2054
 696d 6573 2030 332f 4a61 6e2f 3230 3039
 2043 6861 6e63 656c 6c6f 7220 6f6e 2062
 7269 6e6b 206f 6620 7365 636f 6e64 2062
 6169 6c6f 7574 2066 6f72 2062 616e 6b73
 ffff ffff 0100 f205 2a01 0000 0043 4104
 678a fdb0 fe55 4827 1967 f1a6 7130 b710
 5cd6 a828 e039 09a6 7962 e0ea 1f61 deb6
 49f6 bc3f 4cef 38c4 f355 04e5 1ec1 12de
 5c38 4df7 ba0b 8d57 8a4c 702b 6bf1 1d5f
 ac00 0000 00f9 beb4 d900

上面的文件就是 Bitcoin 的 Genesis Block。它是二進(jìn)制數(shù)據(jù)(以 16 進(jìn)制表示)姐军,每?jī)蓚€(gè)字符表示一個(gè)字節(jié)铁材。乍一看感覺(jué)亂七八糟,但是當(dāng)你了解他們的數(shù)據(jù)格式之后奕锌,一切都不是那么難著觉。

數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu)

Bitcoin 官網(wǎng)上有關(guān)于數(shù)據(jù)格式的具體講解,但是他們的文檔的組織結(jié)構(gòu)并不容易閱讀理解惊暴,所以我們總結(jié)了一個(gè)更直觀的圖表饼丘。

現(xiàn)在是不是清楚多了?注意辽话,我并有沒(méi)把數(shù)據(jù)換成大端格式肄鸽,請(qǐng)自行轉(zhuǎn)換。

計(jì)算額外字段

細(xì)心的同學(xué)可能已經(jīng)注意到了油啤,這些數(shù)據(jù)中不包括幾個(gè)非常重要的字段典徘,Block HashBlock Height益咬,Transaction Hash 以及 Addresses逮诲。不錯(cuò),中本聰在設(shè)計(jì) Bitcoin 的時(shí)候可謂是極度的“摳門(mén)”幽告,能通過(guò)計(jì)算得出的數(shù)據(jù)絕對(duì)不存在鏈上梅鹦。從鏈的設(shè)計(jì)角度來(lái)看,這樣做是絕對(duì)正確的冗锁,它能節(jié)省許多磁盤(pán)空間齐唆,但是這卻給我們帶來(lái)了額外的工作。下面我們分別談?wù)劯鱾€(gè)字段的計(jì)算冻河。

計(jì)算 Block Hash 以及 Transaction Hash

Block 和 Transaction 的 Hash 值都是由相同的算法得出的蝶念,不同點(diǎn)只是在于參與計(jì)算的數(shù)據(jù)不同。對(duì)于 Block Hash 來(lái)講芋绸,我們的輸入數(shù)據(jù)只是 80 字節(jié)的 Block Header,而對(duì)于 Transaction 來(lái)講是整個(gè) Transaction 的數(shù)據(jù)担敌。Block Header 里面是包括 Merkle Root 的摔敛,所以在計(jì)算 Block Hash 的時(shí)候不需要整個(gè) Block 最為輸入。

Hash 值是由輸入數(shù)據(jù)進(jìn)行兩次 sha-256 運(yùn)算得出的全封,其形式如下:
hash = sha256(sha256(data))

我們分別將 Block Header 和整個(gè) Transaction 帶入上述公式便能得到相應(yīng)的 Hash 值马昙。

計(jì)算 Block Height

我們知道桃犬,Bitcoin 的原始數(shù)據(jù)是存儲(chǔ)在 blkxxxxx.data 中的,每個(gè) data 文件中都存放了許多個(gè) Block行楞。如果我們按順序從第 0 字節(jié)開(kāi)始讀攒暇,把其中的所有 Block 都解析出來(lái),我們會(huì)發(fā)現(xiàn)這些 Block 并不是完全有序的子房。換句話(huà)說(shuō)你有可能先讀出第 178 個(gè) Block形用,然后才讀出第 177 個(gè) Block。至于為什么會(huì)這樣证杭,大家可以想想以前用 BT 下載的時(shí)候田度,那個(gè)進(jìn)度條長(zhǎng)什么樣。

所以想要得到正確的 Block Height, 我們就必須對(duì)讀出來(lái)的解愤、無(wú)序的 Block 進(jìn)行排序镇饺。了解 Blockchain 的同學(xué)應(yīng)該知道,Blockchain 的數(shù)據(jù)結(jié)構(gòu)是一個(gè)倒過(guò)來(lái)的單鏈表送讲,我們可以通過(guò) Block Hash 和 Previous Block Hash 來(lái)將這些 Block 重新串聯(lián)起來(lái)奸笤。Genesis Block 的 Previous Block Hash 固定為全 0。這樣一來(lái)我們也就可以得出 Block Height 了哼鬓。

計(jì)算 Addresses

想要支持最開(kāi)始的那種根據(jù)地址查詢(xún) Transaction 的功能监右,我們就必須求出每筆交易的發(fā)款人和收款人地址。這兩個(gè)數(shù)據(jù)分別蘊(yùn)含在 Transaction Input 和 Output 的script字段里面魄宏。求出地址的方法大致分為兩步:

  1. 對(duì)于 Transaction Output秸侣,找出其中的 public key 或 public key hash,再根據(jù)一定的算法計(jì)算出地址宠互。

  2. 對(duì)于 Transaction Input, 從其對(duì)應(yīng)的 Previous Transaction Output 中取出地址味榛,作為它的地址。

限于篇幅予跌,我就不過(guò)多討論第一點(diǎn)了搏色。如果大家感興趣,不妨告訴我們券册,我可以單獨(dú)再用一期來(lái)講解如何解析 Bitcoin Script频轿。但是我想對(duì)第二點(diǎn)進(jìn)行一些補(bǔ)充說(shuō)明。雖然在 Transaction Input 里面你能拿到 public key烁焙,但是我不建議大家直接從 Transaction Input 里面計(jì)算地址航邢。這是因?yàn)榻?jīng)過(guò)隔離見(jiàn)證之后,計(jì)算地址的方式發(fā)生了變化骄蝇,直接從 Input 中解析地址很有可能得到一個(gè)與 Previous Transaction Output 不一樣的地址膳殷。簡(jiǎn)單來(lái)說(shuō)就是,你有可能以張三的名義收了一筆錢(qián)九火,卻用李四的名義花掉了這筆錢(qián)赚窃。張三李四本來(lái)是同一個(gè)人册招,但是因?yàn)檫@個(gè)錯(cuò)誤,計(jì)算賬戶(hù)余額的時(shí)候就會(huì)出現(xiàn)余額為負(fù)數(shù)的情況勒极。

Code

有個(gè) Eth 的實(shí)現(xiàn)
ethLeveldb.go


參考:

https://en.bitcoin.it/wiki/Transaction
http://www.reibang.com/p/637bbdcf17d1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末是掰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辱匿,更是在濱河造成了極大的恐慌键痛,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掀鹅,死亡現(xiàn)場(chǎng)離奇詭異散休,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乐尊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)戚丸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扔嵌,你說(shuō)我怎么就攤上這事限府。” “怎么了痢缎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵胁勺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我独旷,道長(zhǎng)署穗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任嵌洼,我火速辦了婚禮案疲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘麻养。我一直安慰自己褐啡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布鳖昌。 她就那樣靜靜地躺著备畦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪许昨。 梳的紋絲不亂的頭發(fā)上懂盐,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音糕档,去河邊找鬼允粤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的类垫。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼琅坡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悉患!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起榆俺,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤售躁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后茴晋,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體陪捷,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年诺擅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了市袖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烁涌,死狀恐怖苍碟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撮执,我是刑警寧澤微峰,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站抒钱,受9級(jí)特大地震影響蜓肆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谋币,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一仗扬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瑞信,春花似錦厉颤、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至秤涩,卻和暖如春帜乞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筐眷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工黎烈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓照棋,卻偏偏與公主長(zhǎng)得像资溃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烈炭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容