摘要:在比特幣中,這種工作的目標是找到滿足某個特定要求的區塊哈希值。這個區塊哈希值就是工作結果的一個證明。因此,計算工作的目的就是為了尋找到這個證明值。例如哈希算法被廣泛用于驗證文件的一致性上。在區塊鏈中,哈希值用于保證區塊的一致性。
最終內容請以原文為準: https://wangwei.one/posts/789...引言
在 上一篇 文章中,我們實現了區塊鏈最基本的數據結構模型,添加區塊以及和前一個區塊連接在一起。但是,我們的實現方式非常簡單,而真實的比特幣區塊鏈中,每一個區塊的添加都是需要經過大量的計算才可以完成,這個過程就是我們熟知的挖礦。
工作量證明機制區塊鏈最關鍵的一個思想就是,必須進行大量且困難的計算工作才能將交易數據存放到區塊鏈上。這種工作機制才能保證整個區塊鏈數據的安全性和一致性。同時,完成這個計算工作的礦工會得到相應的Token獎勵。
這套機制和我們的現實生活非常相似:我們必須努力工作來賺取報酬用以維持我們的生活。在區塊鏈中,網絡中的礦工們努力工作來維持區塊鏈網絡,為其添加區塊,并且獲得一定的Token獎勵。作為他們工作的成果,一個區塊以安全的方式被組合進了區塊鏈中,這樣就保證了整個區塊鏈數據庫的穩定性。還有一個必須要注意的是,某個礦工完成了計算工作的結果,還必須得到其他所有礦工的認同(證明是正確的),這樣才算完成。
這一整套的計算和證明機制,就稱為Proof-of-Work(工作量證明)。計算工作是非常非常困難的,因為它需要消耗大量的計算機算力資源,即使是性能非常高的計算機都不能非常快地計算出正確的結果。此外,隨著時間的推移,這項計算工作的難度也會隨之增加,目的是為了保證每小時6個新區塊的出塊率。在比特幣中,這種工作的目標是找到滿足某個特定要求的區塊Hash(哈希值)。這個區塊哈希值就是工作結果的一個證明。因此,計算工作的目的就是為了尋找到這個證明值。
最后要注意的是,計算出這個特定的Hash(哈希值)是非常困難的,但是別人來驗證這個Hash值是否正確的時候,是非常簡單的,一下子就能完成。
HashingHash:哈希 | 散列
我們來討論一下Hashing(哈希),對這一塊非常熟悉的朋友可以直接跳過這一段內容。
哈希是一種計算機算法,該算法能夠計算出任意大小數據的哈希值,并且這個哈希值的長度是固定的,256bit。這個被計算出來的哈希值能夠作為這個數據的唯一代表。哈希算法有幾個關鍵的特性:
不可逆性。不能根據一個哈希值推導出原始數據。所以,哈希不是加密。
唯一性。每個數據有且僅有一個唯一的哈希值。
迥異性。原始數據一丁點的變化都將得到完全不一樣的哈希值。
例如:
SHA256("wangwei1") ——> 1e898b7c9adaad86c20139a302ccd5277f81040cab68dc2aecfc684773532652 SHA256("wangwei2") ——> c9cc7417c17318c8aab448cc8ace24c53b6dcf350f5c5fd8e91cbc3b011a179d
哈希算法被廣泛用于驗證文件的一致性上。比如軟件提供商通常會在安裝包上附加一個檢驗碼(checksums),當我們下載完一個軟件安裝包后,可以用哈希函數計算一下這個軟件安裝包的哈希值,然后再和軟件安裝包的檢驗碼做個對比,就可以知道下載的安裝包是否完整、是否有數據丟失。
在區塊鏈中,哈希值用于保證區塊的一致性。每一個區塊被用于進行哈希計算的數據,都包含前一個區塊鏈的哈希值,因此任何人想要修改區塊的數據幾乎是不可能的,他必須要把整個區塊鏈中從創世區塊到最新的區塊的所有哈希值全部重新計算一遍。
你可以腦補一下這個工作量有多大,按照目前計算機的算力來看,幾乎不可能Hashcash
比特幣的工作量證明是使用的是Hashcash算法,一種最初被用于反垃圾郵件的算法,它可以被拆解為以下幾步:
獲取某種公開可知的數據data(在郵件案例中,指的是收件人郵件地址;比特幣案例中,指的是區塊頭)
添加一個計數器counter,初始值設置為0;
計算 data 與 counter拼接字符串的哈希值;
檢查上一步的哈希值是否滿足某個條件,滿足則停止計算,不滿足則 counter 加1,然后重復第3步和第4步,直到滿足這個特定的條件為止。
這是一種粗暴的算法:你改變計數器,計算一個新的哈希值,檢查它,增加計數器,計算一個新的哈希值,循環往復,這就是為什么它需要花費大量計算機算力資源的原因所在。
讓我們來近距離看一下這個特定的條件指的是什么。在原始的Hashcash算法中,這個特殊的要求指的是計算出來的哈希值的前20bit必須全是零,
在比特幣種,這種要求哈希值前面有多少個零打頭的要求是隨著時間的推移而不斷調整的,這是出于設計的目的,盡管在計算機的算力會不斷的提升和越來越多的礦工加入這個網絡中的情況下,都要保證每10min生產一個區塊。
我們演示一下這個算法,
# 計算字符串"I like donuts"的哈希值 SHA256("I like donuts") ——> f80867f6efd4484c23b0e7184e53fe4af6ab49b97f5293fcd50d5b2bfa73a4d0 # 拼接一個計數器值(ca07ca),再次進行Hash計算 SHA256("I like donutsca07ca") ——> 0000002f7c1fe31cb82acdc082cfec47620b7e4ab94f2bf9e096c436fc8cee06
這里的ca07ca是計數器值的十六進制,他表示的十進制值為13240266
即,從0開始,總共計算了13240266次,才計算出I like donuts這個數據的Hash值,滿足前6位(3字節)全是零。代碼實現
思路:定義Pow類1)每次區塊被添加到區塊鏈之前,先要進行挖礦(Pow)
2)挖礦過程中,產生的 Hash 值,如果小于難度目標值則添加進區塊,否則繼續挖礦,直到找到正確的Hash為止
3)最后,驗證區塊Hash是否有效
/** * 工作量證明 * * @author wangwei * @date 2018/02/04 */ @Data public class ProofOfWork { /** * 難度目標位 */ public static final int TARGET_BITS = 20; /** * 區塊 */ private Block block; /** * 難度目標值 */ private BigInteger target; private ProofOfWork(Block block, BigInteger target) { this.block = block; this.target = target; } /** * 創建新的工作量證明,設定難度目標值 ** 對1進行移位運算,將1向左移動 (256 - TARGET_BITS) 位,得到我們的難度目標值 * * @param block * @return */ public static ProofOfWork newProofOfWork(Block block) { BigInteger targetValue = BigInteger.valueOf(1).shiftLeft((256 - TARGET_BITS)); return new ProofOfWork(block, targetValue); } }
設定一個難度目標位TARGET_BITS,表示最終挖礦挖出來Hash值,轉化為二進制后,與256相比,長度少了多少bit,也即二進制前面有多少bit是零.
TARGET_BITS 越大,最終targetValue就越小,要求計算出來的Hash越來越小,也就是挖礦的難度越來越大。
我們這里的TARGET_BITS是固定的,但是在真實的比特幣中,難度目標是隨著時間的推推,會動態調整的。詳見:《精通比特幣 (第二版)》第10章
由于數值比較大,這里要使用BitInteger類型。
準備數據/** * 準備數據 ** 注意:在準備區塊數據時,一定要從原始數據類型轉化為byte[],不能直接從字符串進行轉換 * @param nonce * @return */ private String prepareData(long nonce) { byte[] prevBlockHashBytes = {}; if (StringUtils.isNoneBlank(this.getBlock().getPrevBlockHash())) { prevBlockHashBytes = new BigInteger(this.getBlock().getPrevBlockHash(), 16).toByteArray(); } return ByteUtils.merge( prevBlockHashBytes, this.getBlock().getData().getBytes(), ByteUtils.toBytes(this.getBlock().getTimeStamp()), ByteUtils.toBytes(TARGET_BITS), ByteUtils.toBytes(nonce) ); }
參與Hash運算的如下幾個信息:
前一個區塊(父區塊)的Hash值;
區塊中的交易數據;
區塊生成的時間;
難度目標;
用于工作量證明算法的計數器
詳見:《精通比特幣 (第二版)》第09章Pow算法
/** * 運行工作量證明,開始挖礦,找到小于難度目標值的Hash * * @return */ public PowResult run() { long nonce = 0; String shaHex = ""; System.out.printf("Mining the block containing:%s ", this.getBlock().getData()); long startTime = System.currentTimeMillis(); while (nonce < Long.MAX_VALUE) { String data = this.prepareData(nonce); shaHex = DigestUtils.sha256Hex(data); if (new BigInteger(shaHex, 16).compareTo(this.target) == -1) { System.out.printf("Elapsed Time: %s seconds ", (float) (System.currentTimeMillis() - startTime) / 1000); System.out.printf("correct hash Hex: %s ", shaHex); break; } else { nonce++; } } return new PowResult(nonce, shaHex); }
循環體里面主要以下四步:
準備數據
進行sha256運算
轉化為BigInter類型
與target進行比較
最后,返回正確的Hash值以及運算計數器nonce
驗證區塊Hash有效性/** * 驗證區塊是否有效 * * @return */ public boolean validate() { String data = this.prepareData(this.getBlock().getNonce()); return new BigInteger(DigestUtils.sha256Hex(data), 16).compareTo(this.target) == -1; }修改區塊添加邏輯
/** *創建新區塊
* * @param previousHash * @param data * @return */ public static Block newBlock(String previousHash, String data) { Block block = new Block("", previousHash, data, Instant.now().getEpochSecond(), 0); ProofOfWork pow = ProofOfWork.newProofOfWork(block); PowResult powResult = pow.run(); block.setHash(powResult.getHash()); block.setNonce(powResult.getNonce()); return block; }
創建區塊
創建Pow算法對象
執行Pow算法
保存返回的Hash以及運算計數器
測試運行/** * 測試 * * @author wangwei * @date 2018/02/05 */ public class BlockchainTest { public static void main(String[] args) { Blockchain blockchain = Blockchain.newBlockchain(); blockchain.addBlock("Send 1 BTC to Ivan"); blockchain.addBlock("Send 2 more BTC to Ivan"); for (Block block : blockchain.getBlockList()) { System.out.println("Prev.hash: " + block.getPrevBlockHash()); System.out.println("Data: " + block.getData()); System.out.println("Hash: " + block.getHash()); System.out.println("Nonce: " + block.getNonce()); ProofOfWork pow = ProofOfWork.newProofOfWork(block); System.out.println("Pow valid: " + pow.validate() + " "); } } } /** * 設定TARGET_BITS = 20,得到如下結果: */ Mining the block containing:Genesis Block Elapsed Time: 2.118 seconds correct hash Hex: 00000828ee8289ef6381f297585ef8c952fde93fc2b673ff7cc655f699bb2442 Mining the block containing:Send 1 BTC to Ivan Elapsed Time: 1.069 seconds correct hash Hex: 00000a38c0d7f2ebbd20773e93770298aa8bc0cc6d85fca8756fe0646ae7fea5 Mining the block containing:Send 2 more BTC to Ivan Elapsed Time: 4.258 seconds correct hash Hex: 00000777f93efe91d9aabcba14ab3d8ab8e0255b89818cdb9b93cfa844ad0c7f Prev.hash: Data: Genesis Block Hash: 00000828ee8289ef6381f297585ef8c952fde93fc2b673ff7cc655f699bb2442 Nonce: 522163 Pow valid: true Prev.hash: 00000828ee8289ef6381f297585ef8c952fde93fc2b673ff7cc655f699bb2442 Data: Send 1 BTC to Ivan Hash: 00000a38c0d7f2ebbd20773e93770298aa8bc0cc6d85fca8756fe0646ae7fea5 Nonce: 474758 Pow valid: true Prev.hash: 00000a38c0d7f2ebbd20773e93770298aa8bc0cc6d85fca8756fe0646ae7fea5 Data: Send 2 more BTC to Ivan Hash: 00000777f93efe91d9aabcba14ab3d8ab8e0255b89818cdb9b93cfa844ad0c7f Nonce: 1853839 Pow valid: true總結
我們正在一步一步接近真實的區塊鏈架構,本篇我們實現了挖礦機制,但是我們還有很多關鍵性的功能沒有實現:區塊鏈數據庫的持久性、錢包、地址、交易、共識機制,這些我們后面一步一步來實現
資料源代碼:https://github.com/wangweiX/b...
https://jeiwan.cc/posts/build...
《精通比特幣(第二版)》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/23989.html
摘要:在比特幣中,這種工作的目標是找到滿足某個特定要求的區塊哈希值。這個區塊哈希值就是工作結果的一個證明。因此,計算工作的目的就是為了尋找到這個證明值。例如哈希算法被廣泛用于驗證文件的一致性上。在區塊鏈中,哈希值用于保證區塊的一致性。 showImg(https://segmentfault.com/img/remote/1460000013923267?w=3500&h=2090); 最終...
摘要:本文將基于語言構建簡化版的,來實現數字貨幣。值用于確保的安全。計算是計算敏感的操作,即使在高性能電腦也需要花費一段時間來完成計算這也就是為什么人們購買高性能進行比特幣挖礦的原因。資料源代碼精通比特幣第二版 showImg(https://segmentfault.com/img/remote/1460000013923206?w=1600&h=900); 最終內容請以原文為準:http...
摘要:本文將基于語言構建簡化版的,來實現數字貨幣。值用于確保的安全。計算是計算敏感的操作,即使在高性能電腦也需要花費一段時間來完成計算這也就是為什么人們購買高性能進行比特幣挖礦的原因。資料源代碼精通比特幣第二版 showImg(https://segmentfault.com/img/remote/1460000013923206?w=1600&h=900); 最終內容請以原文為準:http...
摘要:以太坊背后的主要人物是。以太坊通過在區塊鏈上引入智能合約,徹底改變了加密世界。以太坊使用名為以太坊虛擬機的虛擬機執行其智能合約。以太坊最終將利用協議轉向權益證明。截至目前,以太坊在可擴展性方面都失敗了。 不同的區塊鏈智能合約和區塊鏈技術現在風靡一時。越來越多的人出于某種原因試圖進入這個神奇的世界。如果你是這項技術的新手并正在尋找基于區塊鏈的開發平臺的快速入門,那么本指南非常適合你。我們...
摘要:第一節課程概述本課程面向初學者,內容涵蓋以太坊開發相關的基本概念,并將手把手地教大家如何構建一個基于以太坊的完整去中心化應用區塊鏈投票系統。第七節以太坊世界計算機以太坊是一種區塊鏈的實現。交易數據以太坊中每筆交易都存儲在區塊鏈上。 第一節 課程概述 本課程面向初學者,內容涵蓋以太坊開發相關的基本概念,并將手把手地教大家如何構建一個 基于以太坊的完整去中心化應用 —— 區塊鏈投票系統。 ...
閱讀 3661·2021-09-07 09:59
閱讀 721·2019-08-29 15:12
閱讀 803·2019-08-29 11:14
閱讀 1307·2019-08-26 13:27
閱讀 2659·2019-08-26 10:38
閱讀 3134·2019-08-23 18:07
閱讀 1271·2019-08-23 14:40
閱讀 1922·2019-08-23 12:38