關于區(qū)塊鏈如何保持數(shù)據一致性的問題,是我在區(qū)塊鏈研習社里的第四次課程,由于一致性問題涉及到區(qū)塊的結構以及與區(qū)塊鏈的不可篡改這個重要特性,因此這一課對大家深入了解區(qū)塊鏈技術非常重要,我也有必要將之前課程的內容進行整理,同時再結合更詳細的說明,供大家學習。
1、什么是哈希
如果你懂一些編程,相信對這個概念非常熟悉。但是對于一些沒有編程基礎的人而言,對其卻相當陌生,陌生到買了一本區(qū)塊鏈的書籍卻完全看不下去。哈希函數(shù)在區(qū)塊鏈里使用得太普遍,以至于它所有對用戶展示的內容,比如地址,公鑰,私鑰等,都是通過哈希函數(shù)生成的,所以在這里有必要重點對這個概念闡述一下,即便懂得編程,聽過這個概念,希望你也能再看一遍,就當是回顧了。
哈希,英文對應為Hash,一般說的都是哈希函數(shù),百度百科的解釋是:
Hash,一般翻譯做“散列”,也有直接音譯為“哈?!钡?,就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來唯一的確定輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
簡單來講,就是將一個較長的字符串a轉換為一個固定長度的字符串b,然后用b這個串去代表之前的a,比如一個比特幣地址1DQe9F3agsDcr4qoTZ3Sush4e88Nv9tNxa,就是一個哈希值。經過哈希轉換后,無法通過b還原出原來的a。
哈希算法在文件校驗、數(shù)字簽名及鑒權協(xié)議都有很好的應用。在Java編程里,可直接通過hashCode函數(shù)獲取一個字符串的哈希值,哈希算法是一個非常高效的算法,所以使用非常頻繁。
2、簡單的判斷一致性方法
你應該經常下載過東西,可能對一個文件重復下載了兩次,甚至現(xiàn)在還會不小心在一些釣魚網站下載了一些惡意程序,那么你是如何判斷文件的一致性以及識別程序是否有問題呢?
你可能想到的方法有:1)比較文件大小,如果不一致,則說明是不同的文件;2)查看文件內容,但是并不是所有的程序都是文本可讀的;3)查看文件的一些標注信息是否一致,等等。但是這些方法都相當初級,對于一些高級的作弊手段無法識別,正因如此,一些良心網站都會提示比較文件的MD5值,很多細心的朋友應該能發(fā)現(xiàn)這個提示,但是基本也很少按照這個提示去做,畢竟我們大部分人都習慣了在網上“裸奔”。
上面提到的MD5,就是一種被廣泛使用的哈希函數(shù)。現(xiàn)在越來越多的網站都會公布文件的MD5值,用戶在下載文件后可自己進行運算并進行比對,如果一致則說明所下載文件沒被篡改過。
由于工作需要,這兩天我準備下載一個mangodb,這是下載頁面的截圖,通過截圖大家應該能有一個直觀的認識:
當然MD5只是哈希算法的一種,上面的截圖還顯示了其他支持的方法,不過這些都是使用哈希算法的特性用于校驗文件的一致性的。
3、區(qū)塊鏈如何保持數(shù)據的一致性——默克樹
下面這個圖是比特幣的區(qū)塊結構圖,它相當重要以至于每一本區(qū)塊鏈書籍都會介紹,也希望每一個研習社的朋友能掌握:
在上表的第三行“Merkle樹的根值”正是一個哈希值,和上面提到的一樣,區(qū)塊鏈技術正是利用這個哈希值來判斷區(qū)塊的數(shù)據是否被篡改過的。
但是,事情可能還沒想的那么簡單。因為一個區(qū)塊可能包含幾百個甚至更多的交易,其內容會非常多,對整體進行哈希運算效率是非常低下的,因此,才會出現(xiàn)上圖大家可能還相對陌生的詞“Merkle樹”,翻譯為默克樹,這才是保持一致性的關鍵。
默克樹,全稱“默克爾哈希樹”,是一種二叉或多叉的數(shù)據結構,通過對每一個葉子節(jié)點進行哈希計算,并不斷往上遞歸,最后構建成一個樹形結構。因此默克樹是一種被廣泛用于快速歸納和對大規(guī)模數(shù)據進行完整性校驗的數(shù)據結構。
在比特幣的實現(xiàn)中,不用保存每一個交易的哈希值,而是將所有交易構建成這樣一個默克樹,并以樹的根節(jié)點的哈希值作為所有交易內容的一個映射,存放于區(qū)塊的頭部結構中,從而在保證數(shù)據完整性,防止被惡意篡改的同時,極大減少了運算量,提高了運算效率,而且,如果一旦被篡改,還能進行快速定位。簡直是妙不可言!
下面是一張默克樹的圖,大家姑且看之,不懂也無所謂,全當欣賞: