比特幣中的哈希函數(shù)是如何工作的
長(zhǎng)假最后一天,不知道假期結(jié)束甚至幾年后回想起來是否還記得住祖國(guó)70歲生日的這段時(shí)光呢?是否那個(gè)時(shí)候還會(huì)覺得這七天過的有意義呢?除了國(guó)慶閱兵和幾個(gè)讓人值得刷一刷的電影,如果你除了娛樂還沒有什么特別的記憶,不妨讀下本系列文章一分鐘了解比特幣,告訴大家你學(xué)習(xí)到了當(dāng)下最熱門的有關(guān)比特幣的技術(shù)知識(shí),而且是有深度有內(nèi)涵的那種哦。
哈希函數(shù)是一個(gè)只能在一個(gè)方向上計(jì)算的函數(shù),這保證了區(qū)塊鏈?zhǔn)澜绲那逦院桶踩浴_@也意味著,如果我們輸入一個(gè)函數(shù),我們就可以計(jì)算輸出,但是只給輸出卻不可能逆向計(jì)算出輸入。(在這個(gè)意義上,這一特性就像從私鑰中獲取公鑰一樣。)不過,我們現(xiàn)在不討論它背后的數(shù)學(xué)原理或者它是如何工作的。我們需要做的就是理解它的作用,把它當(dāng)成魔術(shù)看待。
我們可以選擇自己所希望的哈希函數(shù)輸出范圍。例如,我們可以使用0到9之間的所有數(shù)字(但是只使用單個(gè)數(shù)字),0到99,0到100萬(wàn),或者是像0到894這樣的確定值。
為了更好地說明哈希函數(shù)是如何工作的,我們可以假設(shè)哈希函數(shù)的范圍是0到9。無(wú)論我們輸入的內(nèi)容是什么,函數(shù)最后都會(huì)得出0到9其中一個(gè)數(shù)字。如果我們輸入一個(gè)表情符號(hào),它可能得出5。如果輸入7859,可能會(huì)得到3。如果我們輸入一篇文章,它可能會(huì)得出數(shù)字7。
哈希函數(shù)總會(huì)輸出一個(gè)數(shù)字,但我們不知道為什么?,F(xiàn)在想象一下我們輸入的是小說文本,但是在文末添加了一個(gè)額外數(shù)字7,你可能認(rèn)為這種輸入方式最后得出的輸出數(shù)是我們?cè)谧詈筝斎氲臇|西,因此自己最后可能得到數(shù)字7。這樣想可就大錯(cuò)特錯(cuò)了。
在哈希函數(shù)中,輸入和輸出沒有可預(yù)測(cè)的相關(guān)性。這種不相關(guān)性可以有效防止黑客入侵,因?yàn)檩斎牒洼敵鰺o(wú)關(guān)就不能找出邏輯上的漏洞。
除了加密貨幣之外,哈希函數(shù)還用于在集中網(wǎng)頁(yè)服務(wù)器上存儲(chǔ)密碼。網(wǎng)絡(luò)數(shù)據(jù)庫(kù)經(jīng)常被黑客攻擊,如果黑客能夠做到成功破解數(shù)據(jù)庫(kù)并讀取每個(gè)人的密碼的話,用戶就要遭殃了。
為了讓用戶更安全,幾乎所有的現(xiàn)代網(wǎng)站都會(huì)對(duì)用戶的密碼進(jìn)行哈希處理,然后再將其存儲(chǔ)到數(shù)據(jù)庫(kù)中。這樣一來,黑客沒有辦法僅憑數(shù)據(jù)庫(kù)里讀取的數(shù)字就算出用戶的密碼。因?yàn)閺妮斎氲捷敵雒恳粋€(gè)哈希函數(shù)都是一個(gè)非常復(fù)雜的代碼,基本無(wú)法破解。黑客讀取數(shù)字的時(shí)候也只能看到一系列毫無(wú)關(guān)聯(lián)的隨機(jī)數(shù)字。
但是,每次用戶登錄時(shí),服務(wù)器都可以正確地驗(yàn)證他們提供的是否是真正的密碼。因?yàn)榉?wù)器只接受正確的密碼,并再次對(duì)密碼進(jìn)行哈希函數(shù)驗(yàn)證,查看它是否與存儲(chǔ)在數(shù)據(jù)庫(kù)中的哈希結(jié)果相匹配。在這種情況下,密碼本身才是關(guān)鍵,獲得“哈?!睌?shù)對(duì)黑客來說毫無(wú)用處。
哈希函數(shù)猜謎游戲
在比特幣領(lǐng)域,我們選擇獎(jiǎng)勵(lì)給礦工發(fā)布區(qū)塊的權(quán)利。礦工可以通過哈希函數(shù)來運(yùn)行他們準(zhǔn)備發(fā)布的區(qū)塊,并且輸出給定范圍內(nèi)的數(shù)字。接著礦工會(huì)把格式數(shù)據(jù)用于一個(gè)有序的、格式化的方式中,并開辟一塊地方用于存儲(chǔ)少量無(wú)用的垃圾數(shù)據(jù)(稱為“nonce”)。這如同我們舉辦一個(gè)比賽,我們告訴玩家添加一個(gè)或兩個(gè)隨機(jī)文章的文本并運(yùn)行它,通過哈希函數(shù)來找到與輸出相匹配的具體數(shù)字。
本質(zhì)上,我們是在反向操作——給定哈希輸出,礦工需要找到合適的輸入。但是,這不是不可能的嗎?不可能的是用某種方法從輸出中推斷出輸入。那么隨機(jī)猜測(cè)是可能的嗎?
讓我們回到哈希函數(shù)的例子,它輸出0到9之間的數(shù)字。想象一下,我們正在玩文本輸入的哈希游戲,如果你編輯文本時(shí)用幾句無(wú)意義的話,只要哈希到3,你就可以得到獎(jiǎng)勵(lì)。游戲很簡(jiǎn)單,因?yàn)閺娜魏屋斎胫械玫?的概率是1 / 10。礦工只需要平均嘗試五種不同的輸入就能獲得獎(jiǎng)勵(lì)。
一臺(tái)速度很快的MacBook上的標(biāo)準(zhǔn)CPU每秒可以在哈希函數(shù)中插入88,000個(gè)猜測(cè)數(shù)值,所以實(shí)際上只需要幾分之一秒的幾分之一秒就可以得到答案。
如果有五十人都使用Macbook參加挑戰(zhàn),而且他們的競(jìng)爭(zhēng)持續(xù)大約一個(gè)小時(shí),你就可以用88000乘以60秒的數(shù)量乘以60分鐘(假設(shè)有人可以做一個(gè)小時(shí)),然后乘以五十多的人數(shù)來計(jì)算可能量。由此可見,哈希函數(shù)的范圍很大:從0到(88000 * 60 * 60 *50),范圍從0到15840000000。你必須猜對(duì)才能得到獎(jiǎng)勵(lì)。
比特幣使用非常大的數(shù)字來表示哈希函數(shù)的范圍,所以對(duì)于玩家來說,即使玩家數(shù)量在不斷增長(zhǎng),每人每天仍然需要用10分鐘來運(yùn)行這個(gè)猜謎游戲。一旦有人贏了游戲,他們寫的新塊就會(huì)被大眾認(rèn)可而發(fā)布。
隨著挖礦消耗的電力越來越多,比特幣網(wǎng)絡(luò)也隨之變化,并根據(jù)計(jì)算前幾個(gè)區(qū)塊的時(shí)間長(zhǎng)短,動(dòng)態(tài)提高每個(gè)區(qū)塊的“難度”。顯然不是說一個(gè)集中化的資源決定了這一點(diǎn),而是每個(gè)礦工通過自己的計(jì)算決定的。
比特幣價(jià)值越高,人們對(duì)它的需求越多,范圍就越廣,因此必須確?!坝螒颉痹诟嗤婕壹尤氲那闆r下仍然保持平等和廣泛。
比特幣實(shí)際上并沒有調(diào)整哈希函數(shù)的范圍來更改游戲的難易程度,而是使用了固定范圍:2的256次方。然而,在比特幣版本的挑戰(zhàn)中,礦工們并不是為了匹配一個(gè)特定的數(shù)字,而是他們的哈希函數(shù)的輸出必須在一定的范圍內(nèi)。
調(diào)整截止值可以降低挑戰(zhàn)難度。例如,如果我們有一個(gè)范圍為1到1000萬(wàn)的哈希函數(shù),我們可以將截止值設(shè)為“2”,那么匹配的概率即為1 / 1000萬(wàn)。而輸出必須等于“1”,礦工才能獲勝?;蛘?,我們可以把截止值設(shè)為500萬(wàn),那么人們?cè)诘谝淮螄L試中獲得成功的幾率達(dá)到50%。
在比特幣系統(tǒng)中,礦工能在第一次嘗試就解決問題的幾率極低,遠(yuǎn)小于一千萬(wàn)分之一,但考慮到獎(jiǎng)品,有人仍然會(huì)再堅(jiān)持十分鐘。
想想看:有了足夠多的刮刮樂彩票,即使你買了幾百?gòu)?,你個(gè)人中獎(jiǎng)的幾率也很低。但是,只要有一張中獎(jiǎng)的彩票,就一定會(huì)有人中獎(jiǎng)。這種確定性和隨機(jī)性取代了中央權(quán)威。
把“鏈”放在區(qū)塊鏈中
一旦礦工成功地解決了上述難題,會(huì)發(fā)生什么?他們?nèi)绾胃嬷溆嗤婕遥克杏脩粲秩绾谓邮苓@個(gè)新塊呢?簡(jiǎn)而言之:經(jīng)過這場(chǎng)比賽,我們?nèi)绾尾拍茏罱K確定一段明確的歷史記錄,以確保游戲的公平性和清晰度呢?
1. 每個(gè)塊必須包含前一個(gè)塊的哈希值
2. 擁有最多礦工信任并在上面繼續(xù)工作的最長(zhǎng)的塊鏈,就是規(guī)范鏈
總之,一旦在網(wǎng)絡(luò)上發(fā)布了一個(gè)新的、有效的塊,礦工就必須撿起這個(gè)新塊并將它放到他們的鏈中,然后立即從頭開始挖掘一個(gè)新的塊。每個(gè)塊必須包含前一個(gè)塊的哈希值,這樣就能確保區(qū)塊鏈不斷更新。
假設(shè)此時(shí)的鏈長(zhǎng)為5個(gè)塊(這是創(chuàng)建比特幣后的50分鐘——一個(gè)塊10分鐘)。這就意味著我們要讓第6塊包含第5塊的哈希值。
但是假如說有人在我們之前挖掘出第6塊,我們就得在挖掘第7塊時(shí)將別人的第6塊哈希值包含進(jìn)來。我們不能一直浪費(fèi)時(shí)間在第6塊上,因?yàn)槿藗円呀?jīng)接受了六個(gè)區(qū)塊是最長(zhǎng)的鏈條,如果我們不趕緊的話,很快就會(huì)有第七個(gè)了。
這意味著如果我們想讓它被接受并獲得獎(jiǎng)勵(lì),我們必須從頭開始創(chuàng)建下一個(gè)塊。而這個(gè)過程中的關(guān)鍵點(diǎn)是,一個(gè)塊只在它之前的另一個(gè)塊的引用中有效。我們所說的“在另一個(gè)塊上”采礦是為了確保塊與塊之間相互聯(lián)系。
如果兩個(gè)塊同時(shí)發(fā)布會(huì)怎樣?礦工會(huì)選擇其中一個(gè)來挖掘頂部,有可能在一段時(shí)間里,有兩個(gè)鏈相互競(jìng)爭(zhēng)。但是,在兩條鏈內(nèi),一個(gè)會(huì)很快變得比另一個(gè)長(zhǎng),當(dāng)另一個(gè)被拋棄的時(shí)候,這個(gè)鏈條會(huì)成為了規(guī)范。
現(xiàn)在我們可以看到重復(fù)消費(fèi)是不可能的:在一個(gè)給定塊上發(fā)布了幾個(gè)塊之后,該塊中的交易實(shí)際上被“埋葬”了,不可能被還原或是記錄到支付歷史中。如果不撤消整個(gè)區(qū)塊鏈,就無(wú)法撤消歷史記錄。
那么,如何撤銷整個(gè)區(qū)塊鏈呢?事實(shí)上,只有當(dāng)你消耗的電力比其他所有人加起來還多的時(shí)候,你才有可能超過其他礦工。這被稱為51%攻擊,因?yàn)槲覀冃枰刂七M(jìn)入系統(tǒng)的51%的電力。如果說比特幣有什么弱點(diǎn)的話,這恰恰是比特幣的弱點(diǎn)。但是,只要這種情況不發(fā)生,系統(tǒng)就是安全的。(這也是比特幣網(wǎng)絡(luò)可能被摧毀的方式。如果一個(gè)參與者持續(xù)進(jìn)行51%攻擊,以一堆垃圾交易來逆轉(zhuǎn)交易過程,那么系統(tǒng)將無(wú)法記錄任何一個(gè)人的支付歷史。)
但這還不算是所有問題中最嚴(yán)重的一個(gè):為了破壞區(qū)塊鏈生態(tài)系統(tǒng),一個(gè)參與者仍然需要花費(fèi)大量的電力,以盡可能快的速度挖掘比特幣從而獲取利潤(rùn)。而且,誰(shuí)想要阻止這種情況(想想其他強(qiáng)大的競(jìng)爭(zhēng)對(duì)手),誰(shuí)就無(wú)法逃脫懲罰,然而值得慶幸的是,一個(gè)礦工的耗電量很難在區(qū)塊鏈的所有電力加和中占到51%。
來源: CertiK