二、 區(qū)塊鏈工作原理—基礎(chǔ)算法篇

Hash算法是區(qū)塊鏈中最核心的算法,在了解區(qū)塊鏈前我們必須先了解關(guān)于Hash算法的一些基本概念。

2.1 Hash的種類:

Hash算法有很多種,其中有MD5、SHA,而SHA算法又分為SHA-1、SHA-224、SHA-256、SHA-384和SHA-512五種變體,區(qū)塊鏈中用到的是SHA256,,所以我們?cè)谶@里會(huì)重點(diǎn)關(guān)注,后面會(huì)講到。

2.2、Hash算法的特點(diǎn):

1、輸入任意長(zhǎng)度的字符串(x)可以得到長(zhǎng)度固定的結(jié)果(H(x)),例如使用MD5算法:

MD5("version1") = "966634ebf2fc135707d6753692bf4b1e";

MD5("version2") = "2e0e95285f08a07dea17e7ee111b21c8";

2、輸入敏感,輸入數(shù)據(jù)的稍微改變就會(huì)引起Hash運(yùn)算結(jié)果的面目全非,上面的例子中“version1”和“version2”僅僅是最后一位“1”和“2”的區(qū)別,得出來(lái)的結(jié)果卻截然不同。

3、免碰撞,即不會(huì)出現(xiàn)輸入x≠y但是H(x) = H(y)的情況,也就是強(qiáng)抗沖突性。

4、原像不可逆,通俗地說(shuō),指的是知道輸入值,很容易通過哈希函數(shù)計(jì)算出哈希值;但知道哈希值,沒有辦法計(jì)算出原來(lái)的輸入值。也就是說(shuō),對(duì)于一個(gè)給定的輸出哈希結(jié)果H(x),想要逆推出輸入x,在計(jì)算上是不可能的,比如上面將“version1”的字符串經(jīng)過MD5算法得出"966634ebf2fc135707d6753692bf4b1e",但是沒有方法在知道輸出值"966634ebf2fc135707d6753692bf4b1e"的情況下,反推出原始值是“version1”。

4)難題友好性,不存在比窮舉更好的方法,以使哈希結(jié)果H(x)落在特定的范圍,換一種說(shuō)法就是,沒有便捷的方法去產(chǎn)生一滿足特殊要求的哈希值。

哈希函數(shù)的難題友好性構(gòu)成了基于工作量證明的共識(shí)算法的基礎(chǔ),例如,給定字符串“blockchain”,并在這個(gè)字符串后面連接一個(gè)整數(shù)值串x,對(duì)連接后的字符串進(jìn)行SHA256哈希運(yùn)算,要求得到的哈希結(jié)果(以十六進(jìn)制的形式表示)以若干個(gè)0開頭的。按照這個(gè)規(guī)則,由x=1出發(fā),遞增x的值,我們需要經(jīng)過2688次哈希計(jì)算才能找到前3位均為0的哈希值,而要找到前6位均為0的哈希值,則需進(jìn)行620969次哈希計(jì)算。也就是說(shuō),沒有更快捷的方法來(lái)產(chǎn)生一個(gè)滿足要求的哈希結(jié)果。

2.3、SHA-256算法

SHA-256屬于Hash算法中的一種,由美國(guó)國(guó)家安全局研發(fā),又屬于SHA算法的變種之一,是SHA-1的后繼者。

SHA256相對(duì)于其他的Hash算法來(lái)說(shuō),特點(diǎn)是對(duì)于任意長(zhǎng)度的消息,SHA256都會(huì)產(chǎn)生一個(gè)256bit長(zhǎng)的哈希值,稱作消息摘要。這個(gè)摘要相當(dāng)于是個(gè)長(zhǎng)度為32個(gè)字節(jié)的數(shù)組,通常用一個(gè)長(zhǎng)度為64的十六進(jìn)制字符串來(lái)表示。

Hash算法作為區(qū)塊鏈中的主要算法對(duì)于區(qū)塊鏈來(lái)說(shuō)有著怎樣的意義,和區(qū)塊鏈的工作原理又有什么關(guān)系?

別急,慢慢往下看。

現(xiàn)在假設(shè)一種場(chǎng)景:

網(wǎng)絡(luò)傳輸數(shù)據(jù)的時(shí)候,A收到B的傳過來(lái)的文件,需要確認(rèn)收到的文件有沒有損壞。如何解決?

最簡(jiǎn)單的方法是對(duì)整個(gè)原始數(shù)據(jù)做Hash運(yùn)算得到固定長(zhǎng)度的Hash值,然后把得到的Hash值公布在網(wǎng)上,這樣用戶從可信的渠道下載到公布的Hash值之后,對(duì)數(shù)據(jù)再次進(jìn)行Hash運(yùn)算,比較運(yùn)算結(jié)果和網(wǎng)上公布的Hash值進(jìn)行比較,如果兩個(gè)Hash值相等,說(shuō)明數(shù)據(jù)在傳輸過程沒有損壞(篡改),反之說(shuō)明數(shù)據(jù)經(jīng)過篡改或損壞。

如果從一個(gè)穩(wěn)定的服務(wù)器(可信的渠道)進(jìn)行下載,采用單一Hash是可取的。但如果數(shù)據(jù)源不穩(wěn)定,一旦數(shù)據(jù)損壞,就需要整個(gè)數(shù)據(jù)重新下載,這種下載的效率是很低的。

為了解決這個(gè)問題,在P2P網(wǎng)絡(luò)中做數(shù)據(jù)傳輸?shù)臅r(shí)候,往往需要把文件拆分很多小的數(shù)據(jù)塊各自傳輸,同時(shí)從多個(gè)機(jī)器上下載拆分過后不同的小數(shù)據(jù)塊,這樣的好處是,如果小數(shù)據(jù)塊在傳輸過程中損壞了,那么只要重新下載這一塊數(shù)據(jù)就行了,不用重新下載整個(gè)文件。

但是這么做的話,新的問題又來(lái)了,怎么去驗(yàn)證小的數(shù)據(jù)塊有沒有損壞?

答案是,下載之前我們會(huì)對(duì)每個(gè)小的數(shù)據(jù)塊分別做Hash運(yùn)算最終得到一個(gè)Hash List。下載的時(shí)候,在下載到真正數(shù)據(jù)之前,我們會(huì)先下載這個(gè)Hash List。

同樣的問題,怎么確定這個(gè)Hash List是正確的呢?

有一種辦法是對(duì)所有的小數(shù)據(jù)塊進(jìn)行Hash運(yùn)算得到每個(gè)小數(shù)據(jù)塊的Hash值然后再用遍歷的辦法與原數(shù)據(jù)塊的Hash值做一一對(duì)比,只有hash list中的每一個(gè)hash都是正確的,我們才會(huì)認(rèn)為這個(gè)hash list是有效的,嗯,好像是可以,但這種方法代價(jià)是不是太大呢,正常場(chǎng)景下數(shù)據(jù)量可是相當(dāng)巨大的,這種方法的效率明顯比較低下。

解決辦法是最開始在生成HashList的時(shí)候把每個(gè)小塊數(shù)據(jù)的Hash值拼到一起,然后對(duì)這個(gè)長(zhǎng)字符串再做一次Hash運(yùn)算,這樣就能得到一個(gè)最終的hash,這個(gè)最終的Hash值我們稱之為Hash Root(Top Hash)。

這就是Hash算法的作用,利用了Hash算法中的敏感性,某一條數(shù)據(jù)中只要有任何一點(diǎn)小的改動(dòng),會(huì)導(dǎo)致計(jì)算出來(lái)的Hash List中的某一條Hash值的不同,而Hash List中的某一條Hash值的不同又會(huì)導(dǎo)致最后算出來(lái)Hash root與原數(shù)據(jù)的Hash Root有著天差地別,簡(jiǎn)單來(lái)說(shuō),我們只需要一個(gè)長(zhǎng)度固定的字符串(Hash Root)就能輕易識(shí)別任意大小的數(shù)據(jù)是否損壞或者經(jīng)過篡改,識(shí)別成本很低。

所以,最終處理就是,下載數(shù)據(jù)的時(shí)候,首先確保從可信的數(shù)據(jù)源得到正確的根Hash,用它來(lái)校驗(yàn)整個(gè)Hash List,然后通過校驗(yàn)后的Hash List校驗(yàn)整個(gè)數(shù)據(jù)塊。

如圖,收件人可以在收到信息后,先比對(duì)節(jié)點(diǎn)1的Hash值,若節(jié)點(diǎn)1沒有錯(cuò)誤則無(wú)需進(jìn)行進(jìn)一步的比對(duì)。若發(fā)現(xiàn)節(jié)點(diǎn)1錯(cuò)誤可以繼續(xù)比對(duì)節(jié)點(diǎn)2和3的值。發(fā)現(xiàn)節(jié)點(diǎn)3無(wú)誤則可以放棄比對(duì)節(jié)點(diǎn)6和7. 找到錯(cuò)誤來(lái)自節(jié)點(diǎn)2,再依次對(duì)節(jié)點(diǎn)4和5運(yùn)算Hash值并發(fā)現(xiàn)錯(cuò)誤源于自節(jié)點(diǎn)4.然后收件人可以重新要求發(fā)信人發(fā)送節(jié)點(diǎn)4的數(shù)據(jù)從而使整個(gè)數(shù)據(jù)和發(fā)件人的保持一致。

現(xiàn)實(shí)生活中我們常用的BT(BitTorrent,一種分布式文件下載協(xié)議)下載就是采用這一套技術(shù)流程,代表性的有迅雷下載,所以大家在用迅雷下載時(shí),有沒有想過,為什么用迅雷下載的時(shí)候有時(shí)候需要先下載一個(gè)“種子”文件呢,這個(gè)“種子文件到底是什么?

其實(shí)這個(gè)種子文件就包含了我們前面所說(shuō)的Hash List和Hash Root,用法自然也是前面的所說(shuō)的——驗(yàn)證數(shù)據(jù)塊是否損壞或者被篡改,保證下載原始數(shù)據(jù)的的完整性和正確性。

這里講了這么多,好像沒有感受到與區(qū)塊鏈有任何聯(lián)系,實(shí)際上這些只是對(duì)基本概念的普及,利用這些基礎(chǔ)信息我們才能開展后面的工作。

OK,進(jìn)入重點(diǎn)。

三、區(qū)塊鏈工作原理—區(qū)塊結(jié)構(gòu)篇

在了解區(qū)塊鏈之前,我們需要知道很重要的一點(diǎn)就是,區(qū)塊鏈?zhǔn)怯伞皡^(qū)塊”這個(gè)基本單元所構(gòu)成。

字面意思就可以看出來(lái),區(qū)塊鏈?zhǔn)怯伞皡^(qū)塊”組成的鏈條,從技術(shù)的角度來(lái)說(shuō),區(qū)塊鏈?zhǔn)且环N分布式數(shù)據(jù)庫(kù)。

如果把區(qū)塊鏈比作一支賬本,那么區(qū)塊就是這個(gè)賬本的一頁(yè)。

“區(qū)塊”的概念如此重要,以至于我們只有真正理解了區(qū)塊,才能真正理解區(qū)塊鏈。

所以,下面我們將會(huì)詳細(xì)“解剖”區(qū)塊,看看區(qū)塊的“五臟六腑”,由內(nèi)往外窺探整個(gè)區(qū)塊鏈的原理。

3.1、先來(lái)區(qū)塊基本組成,如圖

首先,一個(gè)完整的區(qū)塊分為區(qū)塊頭(Block Header)和區(qū)塊體(Block Body)。

什么是區(qū)塊體?區(qū)塊體內(nèi)包含的是一條條交易數(shù)據(jù),列如張三給李四轉(zhuǎn)了一筆賬,轉(zhuǎn)賬者,接收者,金額,時(shí)間等等,這些信息構(gòu)成一條交易數(shù)據(jù),每一個(gè)區(qū)塊的區(qū)塊體都包含著無(wú)數(shù)條數(shù)據(jù),可以理解為,區(qū)塊體才是數(shù)據(jù)真正存儲(chǔ)的地方。

了解了區(qū)塊體,那什么是區(qū)塊頭?區(qū)塊頭是整個(gè)區(qū)塊的核心也是區(qū)塊的元數(shù)據(jù),它的成員變量全都是公共的,這使得它可以很方便的向調(diào)用者提供關(guān)于Block屬性的操作。區(qū)塊頭的組成相對(duì)復(fù)雜,我們一一來(lái)看。

1、Hash

由SHA256算法計(jì)算得出得當(dāng)前區(qū)塊的哈希值,也是代表當(dāng)前區(qū)塊的唯一值,可以理解成我們通常開發(fā)中Id的概念。每個(gè)區(qū)塊都有自己的唯一Hash。

2、父哈希(Pre Hash)

上一個(gè)區(qū)塊的哈希值。每個(gè)一區(qū)塊當(dāng)中都保存著上一個(gè)區(qū)塊的Hash,可以理解為父子關(guān)系,因?yàn)槌说谝粋€(gè)區(qū)塊(創(chuàng)世區(qū)塊),所有區(qū)塊的產(chǎn)生都是基于前一個(gè)區(qū)塊。

3、子哈希(Next Hash)

基于當(dāng)前區(qū)塊所產(chǎn)生的下一個(gè)區(qū)塊的哈希值,當(dāng)前區(qū)塊也就是子區(qū)塊的父區(qū)塊。

看到1、2、3這里可以解決我們一直以來(lái)的一個(gè)疑惑,區(qū)塊鏈里面的“鏈”到底是什么?其實(shí)就是由于每個(gè)區(qū)塊有當(dāng)前Hash 、父Hash、子Hash的概念,這些所謂的“父”,“子”形成了一套完整的順序鏈條,換句話說(shuō),區(qū)塊與區(qū)塊之間并非雜亂無(wú)章,而是存在著嚴(yán)格的順序關(guān)系。而這種順序關(guān)系像極了鏈表的概念,二者的邏輯順序均是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。

鏈表:

區(qū)塊鏈:

注:有一點(diǎn)點(diǎn)小的區(qū)別是區(qū)塊鏈?zhǔn)欠茄h(huán)的,而鏈表是可以有循環(huán)的。

4、版本號(hào)(Version)

系統(tǒng)版本號(hào),可以理解成日常開發(fā)中開發(fā)的軟件版本。

5、區(qū)塊高度(Height)

區(qū)塊鏈網(wǎng)絡(luò)中第幾個(gè)誕生的區(qū)塊序號(hào),例如第一個(gè)區(qū)塊通常也被稱為創(chuàng)世區(qū)塊,高度為0(這很程序員),第十個(gè)產(chǎn)生的區(qū)塊高度為9(區(qū)塊并不是一下子就全有的,例如比特幣區(qū)塊就是每10分鐘產(chǎn)生一個(gè),也就說(shuō)區(qū)塊的“出生”都是有著先后順序的,這個(gè)順序我們會(huì)打上標(biāo)簽,這個(gè)標(biāo)簽就是”高度“)。

6、時(shí)間戳(TimeStamp)

區(qū)塊創(chuàng)建的時(shí)間,同時(shí)也交易數(shù)據(jù)打包進(jìn)區(qū)塊的時(shí)間,區(qū)塊的誕生是伴隨著交易數(shù)據(jù)的打包記錄,保存的地方就是我們前面提到的區(qū)塊體。

7、隨機(jī)數(shù)(Nonce)

一個(gè)從0開始,最大長(zhǎng)度為32位的隨機(jī)數(shù),這里就涉及到挖礦了,所謂的挖礦,就是不停地變更區(qū)塊頭中的隨機(jī)數(shù),并對(duì)每次變更后的區(qū)塊頭(block_header,)做雙重SHA-256運(yùn)算(即SHA256 (SHA 256(Block_Header))),將結(jié)果值哈希反轉(zhuǎn)并與當(dāng)前網(wǎng)絡(luò)的目標(biāo)值對(duì)應(yīng)的十進(jìn)制字符串做對(duì)比,如果小于目標(biāo)值,則解題成功,工作量證明完成。(這里先簡(jiǎn)單了解即可,后面會(huì)重點(diǎn)講到)。

9、難度目標(biāo)(Target Bits)

難度值是礦工們挖礦的重要參考指標(biāo),它決定了礦工大約需要經(jīng)過多少次Hash運(yùn)算才能產(chǎn)生一個(gè)合法的區(qū)塊。比特幣的區(qū)塊大約每10分鐘生成一個(gè),如果要在不同的全網(wǎng)算力條件下,新區(qū)塊的產(chǎn)生都基本保持這個(gè)速率,難度值必須根據(jù)全網(wǎng)算力的變化進(jìn)行調(diào)整。簡(jiǎn)單地說(shuō),難度值被設(shè)定在無(wú)論挖礦能力如何,新區(qū)塊產(chǎn)生速率都保持在10分鐘一個(gè)。

難度值的調(diào)整是在每個(gè)完整節(jié)點(diǎn)中獨(dú)立自動(dòng)發(fā)生的。每隔2016個(gè)區(qū)塊,所有節(jié)點(diǎn)都會(huì)按統(tǒng)一的公式自動(dòng)調(diào)整難度值

公式如下:

新難度值 = 舊難度值*(過去2016個(gè)區(qū)塊花費(fèi)時(shí)長(zhǎng)/20160分鐘)

難度目標(biāo)值= 最大目標(biāo)值/新難度值

而最大目標(biāo)值為一個(gè)恒定值(常量):0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

解題(挖礦)成功的依據(jù)是:

SHA256(SHA256(block_header)) < F(nBits)

? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

? ? (挖礦結(jié)果)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (目標(biāo)值)

10、、Merkle Root(默克爾樹根)

Merkle Root的計(jì)算過程相對(duì)復(fù)雜,一起放到最后的算法環(huán)節(jié)進(jìn)行統(tǒng)一詳細(xì)講解。

區(qū)塊鏈的工作原理—核心算法篇

在這一篇中我們將介紹幾點(diǎn)核心算法,同時(shí)也是整個(gè)區(qū)塊鏈的核心原理。

我們將會(huì)講到:

1、上一篇中提到的Merkle樹是什么?Merkle樹的樹根 —Merkle Root 的算法。

2、區(qū)塊Hash值的算法。

3、挖礦合法性算法驗(yàn)證。

一、Merkle Tree

1、Merkle Tree是一種樹,大多數(shù)是二叉樹,也可以多叉樹,無(wú)論是幾叉樹,它都具有樹結(jié)構(gòu)的所有特點(diǎn);

2、Merkle Tree的葉子節(jié)點(diǎn)的value是數(shù)據(jù)集合(區(qū)塊體中的數(shù)據(jù))的單元數(shù)據(jù)或者單元數(shù)據(jù)HASH。

3、非葉子節(jié)點(diǎn)的value是根據(jù)它下面所有的葉子節(jié)點(diǎn)值,然后按照Hash算法計(jì)算而得出的。

Merkle Tree可以看做前面所說(shuō)Hash List的泛化,Hash List可以看作一種特殊的Merkle Tree,即樹高為2的多叉Merkle Tree,(前面Hash List沒理解清楚的可以往回翻重新理解一下)。

在最底層,和哈希列表一樣,我們把數(shù)據(jù)分成小的數(shù)據(jù)塊,有相應(yīng)地哈希和它對(duì)應(yīng)。但是往上走,注意,這里并不是和Hash List一樣直接去運(yùn)算根哈希,而是把相鄰的兩個(gè)數(shù)據(jù)哈希合并成一個(gè)字符串,然后將這個(gè)由兩個(gè)Hash值拼成的字符串計(jì)算出新的Hash,,這樣每?jī)蓚€(gè)哈希就結(jié)婚生子,得到了一個(gè)”子哈?!?。如果最底層的哈??倲?shù)是單數(shù),那到最后必然出現(xiàn)一個(gè)單身哈希,這種情況就直接對(duì)它進(jìn)行哈希運(yùn)算,所以也能得到它的子哈希。于是往上推,依然是一樣的方式,可以得到數(shù)目更少的新一級(jí)哈希,最終必然形成一棵倒掛的樹,到了樹根的這個(gè)位置,這一代就剩下一個(gè)根哈希了,我們把它叫做 Merkle Root,而這就是所謂的Merkle Root的生成過程。

在p2p網(wǎng)絡(luò)下載網(wǎng)絡(luò)之前,先從可信的源獲得文件的Merkle Tree樹根。一旦獲得了樹根,就可以從其他從不可信的源獲取Merkle tree。通過可信的樹根來(lái)檢查接受到的Merkle Tree。如果Merkle Tree是損壞的或者虛假的,就從其他源獲得另一個(gè)Merkle Tree,直到獲得一個(gè)與可信樹根匹配的Merkle Tree。

Merkle Tree和Hash List的主要區(qū)別是,Merkle Tree可以直接下載并立即驗(yàn)證Merkle Tree的一個(gè)分支。因?yàn)榭梢詫⑽募蟹殖尚〉臄?shù)據(jù)塊,這樣如果有一塊數(shù)據(jù)損壞,僅僅重新下載這個(gè)數(shù)據(jù)塊就行了。如果文件非常大,那么Merkle tree和Hash list都很難做到,但是Merkle tree可以一次下載一個(gè)分支,然后立即驗(yàn)證這個(gè)分支,如果分支驗(yàn)證通過,就可以下載數(shù)據(jù)了。而Hash list只有下載整個(gè)hash list才能驗(yàn)證。(前面花了比較大的篇幅介紹了Hash算法,就是為了讓大家提前了解,如何利用Hash去保證數(shù)據(jù)的一致性,這里的merkle root也是這個(gè)作用,只不過算法上有區(qū)別)

說(shuō)了這么多, Hash Root也好、Merkle Root也罷,不管算法如何,剝開層層外殼,對(duì)于我們而言,它們的核心價(jià)值就是——確保數(shù)據(jù)的真?zhèn)涡裕覀兂Uf(shuō)區(qū)塊鏈的數(shù)據(jù)不可篡改性也就是基于這一點(diǎn)。

區(qū)塊的工作原理—區(qū)塊Hash的生成。

區(qū)塊Hash是代表區(qū)塊的唯一值,這個(gè)值并不是憑空創(chuàng)造,而是和merkle root 、timestamp、nonce息息相關(guān)。

我們采用驗(yàn)證法來(lái)看看這個(gè)值是如何產(chǎn)生的,以比特幣區(qū)塊277316為例。

其信息來(lái)自網(wǎng)站http://blockchain.info

以上是區(qū)塊高度為277316的區(qū)塊的區(qū)塊頭的所有數(shù)據(jù)。

現(xiàn)在開始對(duì)區(qū)塊277316的Hash值進(jìn)行驗(yàn)證。

第一步,準(zhǔn)備數(shù)據(jù)

1、版本號(hào)的十進(jìn)制:2

2、merkle root+pre_hash的16進(jìn)制:

0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569 c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e

3、2013-12-27 23:11:54 的時(shí)間戳:1388185914

4、難度目標(biāo)(Bits)的十進(jìn)制:419668748

5、隨機(jī)數(shù)(nonce)的十進(jìn)制:924591752

第二步,全部轉(zhuǎn)換為16進(jìn)制

1、00000002

2、0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569

? ? ? c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e

3、52be093a

4、1903a30c

5、371c2688

第三步,從big-endian轉(zhuǎn)化為little-endian

先解釋一下什么是endian?簡(jiǎn)單理解就是Big-endian是高字節(jié)在低地址,Litter-endian則高字節(jié)在高地址。

比如 ,int a = 0x05060708

在big-endian的情況下存放為:

字節(jié)號(hào) 0 1 2 3

數(shù)據(jù) 05 06 07 08

在little-endian的情況下存放為:

字節(jié)號(hào) 0 1 2 3

數(shù)據(jù) 08 07 06 05

發(fā)明人中本聰可能為了讓機(jī)器計(jì)算更快,而變?yōu)榱烁咏鼨C(jī)器的編碼方式little-endian.

好,回到正題,所以第二步的數(shù)據(jù) 我們?cè)龠M(jìn)行一次轉(zhuǎn)化,得到了

1、02000000

2、69054f28012b4474caa9e821102655cc74037c415ad2bba70200000000000000

? 2ecfc74ceb512c5055bcff7e57735f7323c32f8bbb48f5e96307e5268c001cc9(到這里的時(shí)候已經(jīng)拼成一個(gè)字符串了)

3、3a09be52

4、0ca30319

5、88261c37

第四步,拼接字符串,開始驗(yàn)證

1、我們將上面準(zhǔn)備的字符數(shù)據(jù)重新拼接成一個(gè)新的字符串,這個(gè)字符串我們稱之為“block_header”:

02000000

+

69054f28012b4474caa9e821102655cc74037c415ad2bba702000000000000002ecfc74ceb512c5055bcff7e57735f7323c32f8bbb48f5e96307e5268c001cc9

+

3a09be52

+

0ca30319

+

88261c37

最終拼接得到的字符串block_header為:

0200000069054f28012b4474caa9e821102655cc74037c415ad2bba702000000000000002ecfc74ceb512c5055bcff7e57735f7323c32f8bbb48f5e96307e5268c001cc93a09be520ca3031988261c37

2、將上面的 block_header轉(zhuǎn)成hex形式得到:

b'\x02\x00\x00\x00i\x05O(\x01+Dt\xca\xa9\xe8!\x10&U\xcct\x03|AZ\xd2\xbb\xa7\x02\x00\x00\x00\x00\x00\x00\x00.\xcf\xc7L\xebQ,PU\xbc\xff~Ws_s#\xc3/\x8b\xbbH\xf5\xe9c\x07\xe5&\x8c\x00\x1c\xc9:\t\xbeR\x0c\xa3\x03\x19\x88&\x1c7'

3、對(duì)這個(gè)值進(jìn)行兩次SHA256運(yùn)算,為什么要兩次,這是因?yàn)镾HA1在2017年被攻破,采用的方法是birthday collision attack。社區(qū)覺得SHA2被攻破也是時(shí)間的問題,而抵御birthday collision attack的有效方法為雙重哈希算法,當(dāng)然這種說(shuō)法只是網(wǎng)上傳言,沒有得到具體確認(rèn)。

偽代碼:SHA256(SHA256(Hex(block_header))),最終得到:

b'\xc4\xbd\xc7,\x1b\xb3\xa9D\xd9\xf2~\xb9(\xa9\xc4A\xdb\x96^\t;\xa1\xb9\xb6\x01\x00\x00\x00\x00\x00\x00\x00'

3、重新編碼得到:

c4bdc72c1bb3a944d9f27eb928a9c441db965e093ba1b9b60100000000000000

看到后面有一堆0,感覺勝利的曙光快來(lái)了。其實(shí)這里實(shí)際上已經(jīng)完成了,但是得到這個(gè)值是little-endian小端模式的,比特幣區(qū)塊上所記錄的值也確實(shí)是這個(gè)值,但是我們?cè)谄匠J褂煤途W(wǎng)頁(yè)瀏覽展示時(shí),都是使用Big-endian大端順序

所以這里我們?cè)龠M(jìn)行一次從little-endian轉(zhuǎn)化為big-endian,就能得到:

0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4

大功告成,看看http://blockchain.info所查詢到的,完全一致,說(shuō)明我們的方法是正確的,區(qū)塊Hash的算法就是我們前面的驗(yàn)算步驟。

總的來(lái)說(shuō),算法不難,最難的地方就在于親自驗(yàn)算的過程中,要把所有的隱藏知識(shí)都挖掘出來(lái)。中文資料中,極少有人做詳細(xì)的通篇驗(yàn)算,而一旦真正理解了驗(yàn)算的過程,我們會(huì)發(fā)現(xiàn)比特幣的算法真的不難。

附:

整個(gè)第四步的Python代碼如下:

有興趣的可以將這一段代碼copy到python開發(fā)工具中運(yùn)行試試,看看得到的值是否如上所說(shuō)。也可以依照上面的步驟驗(yàn)證其他區(qū)塊加強(qiáng)理解。

區(qū)塊的合法性驗(yàn)證

如何確認(rèn)區(qū)塊的合法性,前面在介紹區(qū)塊頭時(shí)有提及過,簡(jiǎn)而言之就是區(qū)塊Hash必須要小于Target Bits (目標(biāo)難度值),這里我們繼續(xù)采用驗(yàn)算法。

區(qū)塊Hash值在上一節(jié)已經(jīng)得到驗(yàn)證,我們算出的是

0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4

Target Bits在上面也已經(jīng)記錄了,是

419668748

數(shù)據(jù)都準(zhǔn)備好了,要驗(yàn)證區(qū)塊是否合法還不簡(jiǎn)單嗎,直接對(duì)比兩個(gè)值的大小不就完了?

真有這么簡(jiǎn)單嗎?

事實(shí)上所謂的“對(duì)比大小”也是有一套完整的換算流程的。

具體怎么換算,這里還們還是按照老套路,采用驗(yàn)證法一步步走。

1、準(zhǔn)備數(shù)據(jù)

Bits :419668748?

最大目標(biāo)值:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

Hash:0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4

2、將Bits 轉(zhuǎn)成 16進(jìn)制得到:

1903a30c

3、將1903a30c進(jìn)行拆分,前2位我們稱為冪者指數(shù),后面6位稱為系數(shù),拆分后得到

19? 03a30c

3、將拆分的值代入固定公式:

目標(biāo)值=系數(shù)*2^(8*(冪者指數(shù)-3))次方

即:目標(biāo)值 = 0x03a30c*2^(8*(0x19-3))

最終計(jì)算出來(lái)的就是真正意義上的目標(biāo)值了。

0000000000000003a30c00000000000000000000000000000000000000000000

4、驗(yàn)算結(jié)果

target bits:

0000000000000003a30c00000000000000000000000000000000000000000000

target:

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

>

0000000000000003a30c00000000000000000000000000000000000000000000

計(jì)算結(jié)果小于難度目標(biāo),符合要求,那這個(gè)結(jié)果就一定是網(wǎng)站上公布的數(shù)字了。

正確的hash值

在挖礦時(shí),nonce隨機(jī)數(shù)是未知的,要從0試到2^32,但是這個(gè)數(shù)字其實(shí)不大,只有4294967296次。以現(xiàn)在的一臺(tái)礦機(jī)動(dòng)輒14T每秒的算力,全部算完到上限也不需要一秒。所以需要使用創(chuàng)幣交易中的附帶信息,額外的字符串成為extra nonce,例如中本聰在比特幣的創(chuàng)世區(qū)塊中寫道“The Times 03/Jan/2009 Chancellor on brink of second ballout for banks”(英國(guó)泰晤士報(bào)2009年1月3日文,財(cái)政大臣正處于實(shí)施第二輪銀行緊急援助的邊緣)嘲諷中心化的銀行。

在2013年年底時(shí),區(qū)塊產(chǎn)生,這需要算力達(dá)到8T/s的設(shè)備,即每秒8*10^15次暴力驗(yàn)證,連續(xù)工作10分鐘。這對(duì)于2018年的現(xiàn)在來(lái)說(shuō)的確不算什么,一臺(tái)礦機(jī),不比兩三塊磚頭大多少,就擁有14T/s的算力,只需要6,7分鐘單獨(dú)就可以挖到。但在當(dāng)時(shí),8T也是全網(wǎng)千分之一的算力了,需要當(dāng)時(shí)最好的礦機(jī)上百臺(tái)一起工作。而如果這個(gè)計(jì)算使用一臺(tái)普通的桌面電腦,需要26年。如果使用一臺(tái)iphoneX的話,每秒可以做70次計(jì)算,那么將需要四百萬(wàn)年。

通過上面的算法我們完整地回顧了比特幣區(qū)塊鏈的工作量證明算法,如果各位完全理清了其中的思路,也就可以手動(dòng)實(shí)現(xiàn)自己的挖礦程序,或者另外嘗試設(shè)計(jì)一些新的區(qū)塊鏈產(chǎn)品了。最艱深的技術(shù),我們希望能夠在底層去了解,然而撥開云霧,其實(shí)底層的邏輯并不難。

不過比特幣里面的技術(shù)遠(yuǎn)不止挖礦算法,加密算法,Script智能合約,各種協(xié)議,各種網(wǎng)絡(luò),交易的驗(yàn)證,每一個(gè)都充滿了魔性,進(jìn)出之間,不由得讓人驚嘆發(fā)明人知識(shí)的深度與廣度。無(wú)論比特幣是什么,將會(huì)怎樣,但是以比特幣為第一個(gè)大規(guī)模應(yīng)用的區(qū)塊鏈技術(shù),已經(jīng)擴(kuò)散了開來(lái),整個(gè)系統(tǒng)的嚴(yán)密與邏輯的復(fù)雜,的確讓人著迷。

更多

對(duì)于創(chuàng)世區(qū)塊,版本號(hào)是1,高度為0(這很程序員),。

前一區(qū)塊的hash值,猜想會(huì)是什么呢?對(duì)于創(chuàng)世區(qū)塊,是沒有前一區(qū)塊,中本聰默認(rèn)寫成了0000000000000000000000000000000000000000000000000000000000000000

難度目標(biāo)是1,這是定義為一個(gè)sha256結(jié)果的前32位是0,也就是對(duì)應(yīng)的16進(jìn)制字符串要有8個(gè)0,那么難度bits此時(shí)是0x1d00ffff。這個(gè)數(shù)字的得出需要概率論的知識(shí),同時(shí)也是中本聰?shù)囊粋€(gè)規(guī)定。

更多區(qū)塊信息可以前往http://blockchain.info查詢,或許會(huì)有更多發(fā)現(xiàn)哦。

其他工具

https://hash.online-convert.com/sha256-generatorSHA-256在線驗(yàn)證

https://webbtc.com/? 獲取區(qū)塊的json數(shù)據(jù)

http://blockexplorer.com/q/getdifficulty查詢比特幣的當(dāng)前難度

http://bitcoin.sipa.be/查看難度的變化情況

http://blockexplorer.com/q/getblockcount查詢比特幣的區(qū)塊數(shù)

https://bitcoin.org/en/developer-reference比特幣區(qū)塊鏈更詳細(xì)的講解(英文)

參考文章:

https://blog.csdn.net/wo541075754/article/details/54632929

http://www.itdecent.cn/p/c6ef67755105

http://www.cnblogs.com/zhaoweiwei/p/difficulty.html

https://blog.csdn.net/jason_cuijiahui/article/details/79011118

https://blog.csdn.net/chaiyu2002/article/details/81237971

https://www.8btc.com/article/9688

第三章—java簡(jiǎn)單實(shí)現(xiàn)區(qū)塊鏈

前面兩章說(shuō)了許多關(guān)于區(qū)塊鏈的理論知識(shí),這一章我們將會(huì)將前面的所有的理論知識(shí)結(jié)合起來(lái),用java簡(jiǎn)答實(shí)現(xiàn)一套區(qū)塊鏈。

基于面向?qū)ο蟮乃枷?,首?/p>

1、定義區(qū)塊鏈的類塊

import java.util.Date;

public class Block {

public String hash;//區(qū)塊Hash

public String previousHash;//前導(dǎo)Hash

private String data; //可以理解為前面講到的區(qū)塊結(jié)構(gòu)里的區(qū)塊體里打包的交易數(shù)據(jù)

private long timeStamp; //時(shí)間戳

//Block Constructor.

public Block(String data,String previousHash ) {

this.data = data;

this.previousHash = previousHash;

this.timeStamp = new Date().getTime();

}

}

2、創(chuàng)建數(shù)字簽名

創(chuàng)建一個(gè)StringUtil,封裝了sha256方法,方便后面調(diào)用,因?yàn)檫@是一個(gè)工具類,所以我們可以不關(guān)心它的具體實(shí)現(xiàn)方式,只要知道它是sha256的java實(shí)現(xiàn)即可。

import java.security.MessageDigest;

public class StringUtil {

//Applies Sha256 to a string and returns the result.

public static String applySha256(String input){

try {

MessageDigest digest = MessageDigest.getInstance("SHA-256"); ? ? ? ?

//Applies sha256 to our input,

byte[] hash = digest.digest(input.getBytes("UTF-8")); ? ? ? ?

StringBuffer hexString = new StringBuffer(); // This will contain hash as hexidecimal

for (int i = 0; i < hash.length; i++) {

String hex = Integer.toHexString(0xff & hash[i]);

if(hex.length() == 1) hexString.append('0');

hexString.append(hex);

}

return hexString.toString();

}

catch(Exception e) {

throw new RuntimeException(e);

}

}

}

接下來(lái)讓我們?cè)贐lock類中應(yīng)用 方法 applySha256 方法,其主要的目的就是計(jì)算hash值,我們計(jì)算的hash值應(yīng)該包括區(qū)塊中所有我們不希望被惡意篡改的數(shù)據(jù),再加上preHash,data和timeStamp,這在上面已經(jīng)演示過了,是一套固定公式,所以這里沒有什么爭(zhēng)議。

//簡(jiǎn)化了計(jì)算方式

public String calculateHash() {

String calculatedhash = StringUtil.applySha256(

previousHash +

Long.toString(timeStamp) +

data

);

return calculatedhash;

}

然后把這個(gè)方法加入到Block的構(gòu)造函數(shù)中去

public Block(String data,String previousHash ) {

this.data = data;

this.previousHash = previousHash;

this.timeStamp = new Date().getTime();

this.hash = calculateHash();

}

3、測(cè)試

在主方法中讓我們創(chuàng)建一些區(qū)塊,并把其hash值打印出來(lái),來(lái)看看是否一切都在我們的掌控中。

第一個(gè)塊稱為創(chuàng)世紀(jì)區(qū)塊,因?yàn)樗穷^區(qū)塊,所以我們只需輸入“0”作為前一個(gè)塊的previous hash。

public class NoobChain {

public static void main(String[] args) {

Block genesisBlock = new Block("Hi im the first block", "0");

System.out.println("Hash for block 1 : " + genesisBlock.hash);

Block secondBlock = new Block("Yo im the second block",genesisBlock.hash);

System.out.println("Hash for block 2 : " + secondBlock.hash);

Block thirdBlock = new Block("Hey im the third block",secondBlock.hash);

System.out.println("Hash for block 3 : " + thirdBlock.hash);

}

}

打?。?/p>

Hash for block 1: f6d1bc5f7b0016eab53ec022db9a5d9e1873ee78513b1c666696e66777fe55fb

Hash for block 2: 6936612b3380660840f22ee6cb8b72ffc01dbca5369f305b92018321d883f4a3

Hash for block 3: f3e58f74b5adbd59a7a1fc68c97055d42e94d33f6c322d87b29ab20d3c959b8f

每一個(gè)區(qū)塊都必須要有自己的數(shù)據(jù)簽名即hash值,這個(gè)hash值依賴于自身的信息(data)和上一個(gè)區(qū)塊的數(shù)字簽名(previousHash),但這個(gè)還不是區(qū)塊鏈,下面讓我們存儲(chǔ)區(qū)塊到數(shù)組中,這里我會(huì)引入gson包,目的是可以用json方式查看整個(gè)一條區(qū)塊鏈結(jié)構(gòu)。

import java.util.ArrayList;

import com.google.gson.GsonBuilder;

public class NoobChain {

public static ArrayList<Block> blockchain = new ArrayList<Block>();

public static void main(String[] args) {

//add our blocks to the blockchain ArrayList:

blockchain.add(new Block("Hi im the first block", "0"));

blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));

blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));

String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);

System.out.println(blockchainJson);

}

}這樣的輸出結(jié)構(gòu)就更類似于我們所期待的區(qū)塊鏈的樣子。

4、檢查區(qū)塊鏈的完整性

在主方法中增加一個(gè)isChainValid()方法,目的是循環(huán)區(qū)塊鏈中的所有區(qū)塊并且比較hash值,這個(gè)方法用來(lái)檢查hash值是否是于計(jì)算出來(lái)的hash值相等,同時(shí)previousHash值是否和前一個(gè)區(qū)塊的hash值相等。(第二章講到過,驗(yàn)證區(qū)塊的有效性即重新計(jì)算區(qū)塊的Hash值并與鏈上記錄的區(qū)塊Hash值是否一致,而上一個(gè)區(qū)塊的Hash值—preHash,又影響了當(dāng)前Hash的計(jì)算)

所以我會(huì)的驗(yàn)證方法就會(huì)這么寫:

public static Boolean isChainValid() {

Block currentBlock;

Block previousBlock;

//遍歷整個(gè)區(qū)塊鏈

for(int i=1; i < blockchain.size(); i++) {

currentBlock = blockchain.get(i);

previousBlock = blockchain.get(i-1);

//當(dāng)重新計(jì)算區(qū)塊Hash發(fā)現(xiàn)和鏈上記錄的不相等時(shí)

if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){

System.out.println("Current Hashes not equal");

return false;

}

//當(dāng)上一個(gè)區(qū)塊上的Hash和當(dāng)前區(qū)塊記錄的preHash不相等時(shí)

if(!previousBlock.hash.equals(currentBlock.previousHash) ) {

System.out.println("Previous Hashes not equal");

return false;

}

}

return true;

}

任何區(qū)塊鏈中區(qū)塊的一絲一毫改變都會(huì)導(dǎo)致這個(gè)函數(shù)返回false,也就證明了區(qū)塊鏈無(wú)效了。

5、挖礦

這里我們要求挖礦者做工作量證明,具體的方式是在區(qū)塊中嘗試不同的參數(shù)值直到它的hash值是從一系列的0開始的。讓我們添加一個(gè)名為nonce的int類型以包含在我們的calculatehash()方法中,以及需要的mineblock()方法

public class Block {

public String hash;

public String previousHash;

private String data; //our data will be a simple message.

private long timeStamp; //as number of milliseconds since 1/1/1970.

private int nonce;

//區(qū)塊的構(gòu)造?

public Block(String data,String previousHash ) {

this.data = data;

this.previousHash = previousHash;

this.timeStamp = new Date().getTime();

this.hash = calculateHash();

}

//基于交易數(shù)據(jù)信息和其他數(shù)據(jù)生成當(dāng)前區(qū)塊的hash

public String calculateHash() {

String calculatedhash = StringUtil.applySha256(

previousHash +

Long.toString(timeStamp) +

Integer.toString(nonce) +

data

);

return calculatedhash;

}

public void mineBlock(int difficulty) {

String target = new String(new char[difficulty]).replace('\0', '0');? ? ? ? //計(jì)算出的Hash要求前面多少個(gè)0(理論上前面的0要求越多代表挖礦難度越大)

while(!hash.substring( 0, difficulty).equals(target)) {

nonce ++;

hash = calculateHash();

}

System.out.println("Block Mined!!! : " + hash);

}

}

mineBlock()方法中引入了一個(gè)int值稱為difficulty難度,低的難度比如1和2,普通的電腦基本都可以馬上計(jì)算出來(lái),我的建議是在4-6之間進(jìn)行測(cè)試,普通電腦大概會(huì)花費(fèi)3秒時(shí)間,在萊特幣中難度大概圍繞在442592左右,而在比特幣中每一次挖礦都要求大概在10分鐘左右,當(dāng)然根據(jù)所有網(wǎng)絡(luò)中的計(jì)算能力,難度也會(huì)不斷的進(jìn)行修改。

我們?cè)贜oobChain類 中增加difficulty這個(gè)靜態(tài)變量。

public static int difficulty = 5;

這樣我們必須修改主方法中讓創(chuàng)建每個(gè)新區(qū)塊時(shí)必須觸發(fā)mineBlock()方法,而isChainValid()方法用來(lái)檢查每個(gè)區(qū)塊的hash值是否正確,整個(gè)區(qū)塊鏈?zhǔn)欠袷怯行У摹?/p>

public class NoobChain {

public static ArrayList<Block> blockchain = new ArrayList<Block>();

public static int difficulty = 5;

public static void main(String[] args) {

//手動(dòng)創(chuàng)建幾個(gè)區(qū)塊

blockchain.add(new Block("Hi im the first block", "0"));

System.out.println("Trying to Mine block 1... ");

blockchain.get(0).mineBlock(difficulty);

blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));

System.out.println("Trying to Mine block 2... ");

blockchain.get(1).mineBlock(difficulty);

blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));

System.out.println("Trying to Mine block 3... ");

blockchain.get(2).mineBlock(difficulty);

System.out.println("\nBlockchain is Valid: " + isChainValid());

String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);

System.out.println("\nThe block chain: ");

System.out.println(blockchainJson);

}

public static Boolean isChainValid() {

Block currentBlock;

Block previousBlock;

String hashTarget = new String(new char[difficulty]).replace('\0', '0');

//遍歷區(qū)塊,驗(yàn)證有效性

for(int i=1; i < blockchain.size(); i++) {

currentBlock = blockchain.get(i);

previousBlock = blockchain.get(i-1);

//當(dāng)重新計(jì)算區(qū)塊Hash發(fā)現(xiàn)和鏈上記錄的不相等時(shí)

if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){

System.out.println("Current Hashes not equal");

return false;

}

//當(dāng)上一個(gè)區(qū)塊上的Hash和當(dāng)前區(qū)塊記錄的preHash不相等時(shí)

if(!previousBlock.hash.equals(currentBlock.previousHash) ) {

System.out.println("Previous Hashes not equal");

return false;

}

//這里涉及到的其實(shí)就挖礦算法,通過不斷變化的nonce值來(lái)生成Hash值,如果生成的Hash值的前幾位的都是0且和target要求的位數(shù)一致,代表這個(gè)隨機(jī)數(shù)生成的區(qū)塊是有效的。

if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {

System.out.println("This block hasn't been mined");

return false;

}

}

return true;

}

}

打?。?/p>

Trying to Mine block 1...

Block Mined!!! : 0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082

Trying to Mine block 2...

Block Mined!!! : 000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a

Trying to Mine block 3...

Block Mined!!! : 000000576987e5e9afbdf19b512b2b7d0c56db0e6ca49b3a7e638177f617994b

Blockchain is Valid: true

[

? {

? ? "hash": "0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082",

? ? "previousHash": "0",

? ? "data": "first",

? ? "timeStamp": 1520659506042,

? ? "nonce": 618139

? },

? {

? ? "hash": "000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a",

? ? "previousHash": "0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082",

? ? "data": "second",

? ? "timeStamp": 1520659508825,

? ? "nonce": 1819877

? },

? {

? ? "hash": "000000576987e5e9afbdf19b512b2b7d0c56db0e6ca49b3a7e638177f617994b",

? ? "previousHash": "000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a",

? ? "data": "third",

? ? "timeStamp": 1520659515910,

? ? "nonce": 1404341

? }

]

經(jīng)過測(cè)試增加一個(gè)新的區(qū)塊即挖礦必須花費(fèi)一定時(shí)間,大概是3秒左右,你可以提高difficulty難度來(lái)看,它是如何影響數(shù)據(jù)難題所花費(fèi)的時(shí)間的

如果有人在你的區(qū)塊鏈系統(tǒng)中惡意篡改數(shù)據(jù):

他們的區(qū)塊鏈?zhǔn)菬o(wú)效的。

他們無(wú)法創(chuàng)建更長(zhǎng)的區(qū)塊鏈

網(wǎng)絡(luò)中誠(chéng)實(shí)的區(qū)塊鏈會(huì)在長(zhǎng)鏈中更有時(shí)間的優(yōu)勢(shì)

因?yàn)榇鄹牡膮^(qū)塊鏈將無(wú)法趕上長(zhǎng)鏈和有效鏈,除非他們比你網(wǎng)絡(luò)中所有的節(jié)點(diǎn)擁有更大的計(jì)算速度,可能是未來(lái)的量子計(jì)算機(jī)或者是其他什么。

如果你耐心的看到這里了,恭喜,我們已經(jīng)基本創(chuàng)建了屬于自己的區(qū)塊鏈

它有:

有很多區(qū)塊組成用來(lái)存儲(chǔ)數(shù)據(jù)

有數(shù)字簽名讓你的區(qū)塊鏈鏈接在一起

需要挖礦的工作量證明新的區(qū)塊

可以用來(lái)檢查數(shù)據(jù)是否是有效的同時(shí)是未經(jīng)篡改的

結(jié)語(yǔ):

坦白說(shuō),這篇文章更多的是從代碼講解的角度來(lái)剖析區(qū)塊鏈的工作原理,為的是讓大家更好的吸收前面所講解的知識(shí)點(diǎn),雖然有一些偽代碼的成分,但是我們確實(shí)完成了區(qū)塊鏈所有應(yīng)該有的功能。當(dāng)然,真正的區(qū)塊鏈實(shí)現(xiàn)遠(yuǎn)不止這么一點(diǎn),大量的實(shí)現(xiàn)細(xì)節(jié)值得我們?nèi)パ芯?、探討和?shí)現(xiàn),更多的我們后續(xù)會(huì)再講到。

?著作權(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)容

  • 1 貨幣的演變——從貝殼到比特幣 當(dāng)社會(huì)分工產(chǎn)生之后,人類就產(chǎn)生了商品交換的需求。在貨幣被發(fā)明之前,人類是以以物換...
    longlee閱讀 7,931評(píng)論 1 23
  • What is Block chain? A blockchain, originally block chain...
    R0b1n_L33閱讀 1,520評(píng)論 0 0
  • 2017年11月20日 星期一 晴 今天在放學(xué)的路上,爺爺給我買了一本書《父與子》。 ...
    周依澤閱讀 290評(píng)論 0 1
  • 剛來(lái)深圳實(shí)習(xí)的時(shí)候,一個(gè)朋友來(lái)深圳玩,約在深圳灣公園見面。當(dāng)時(shí)對(duì)深圳也不熟,不會(huì)坐地鐵,大老遠(yuǎn)從羅湖坐公交顛過去,...
    愛拍照的射雞師閱讀 1,157評(píng)論 0 1

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