在上一篇文章 :編程小白模擬簡易比特幣系統(一)中,我們明白了區塊和區塊鏈的概念,創建了創世區塊,同時也留下了兩個問題:
區塊結構中,工作量證明是什麼?第二個區塊是怎麼來的?
那麼請大家繼續往下看👇
相關概念
挖礦⛏是什麼?
挖礦這個詞想必大家早已聽聞,但一直不太清楚到底是在幹什麼,也許會知道計算機在不停的計算,那我就基於個人的理解給大家分享一下:
上回書我們談到區塊鏈是由區塊一塊一塊連接得到的,那麼到底是誰有權利去決定下一個區塊是什麼呢?也就是說在這個有我們所有人的交易記錄的大賬本中,是誰去記錄下一頁呢?這就引出了我們挖礦的概念。
每個區塊的產生都需要所有人去解決一個數學難題,誰可以答上來,誰就有權利。前面提到,區塊中有一個信息是當前區塊的hash值,它就是這個數學難題的答案。哈希值我們都知道,就是一個字符串。大家可能想,計算一個字符串有什麼難的,我的電腦分分鐘千萬個Hello world!
那麼大家可不要小瞧這個難題的工作量!計算符合一定條件限制的hash需要耗費大量的算力,比特幣目前規定的hash要求是十多個零開頭,我們的個人筆記本電腦可能得算個幾年幾十年的。
至此,解決了這個難題就獲得了記賬的權利,但是耗費如此大的算力去計算這個難題,僅僅只獲得記賬的權利是不是太虧了?所以系統還會分發給難題解決者一部分比特幣作爲獎勵。這個計算的過程,被形象的稱爲挖礦。
工作量證明是什麼?
細心的朋友應該已經發現上面挖礦過程中,我已經提到了工作量,沒錯,工作量就是整個計算過程耗費的算力。上篇文章講過:
區塊的哈希值 = 上一個區塊的哈希值+ 交易信息 + 隨機數
那麼對於這個球球幣系統來說,隨機數可以從1開始遞增,直到達到要求的hash,隨機數就代表了計算的次數,我們可以簡單的把它當作我們的工作量證明。
第二個區塊是怎麼來的?
解決了數學難題,因此獲得了記賬的權利,所以有權利去補充下一頁賬本了,也就是新區塊要生成了!
在求解數學難題的時候,也許期間會發生許多交易。因此,我們需要把發生的交易記錄下來,這裏注意,我們剛剛挖礦的時候,系統也獎勵了我們一筆球球幣,這也是一筆交易,所以我們在記賬的時候同樣需要記錄。
那麼挖礦的大致流程就可以理解爲:
說了這麼多,相信各位對這些概念似懂非懂,不過沒關係,還是落實到代碼上來的實在一點👇
相關僞代碼
對照上面的流程圖,我們不難寫出這樣的代碼。那麼關於交易,我們暫時先把它當成一個普通的object就好,之後會提到,並且對挖礦代碼做出修改,這裏的重點是理解挖礦的流程。
public Block mine(){
//之前需要記錄的交易
Transaction transaction1 = new Transaction();
Transaction transaction2 = new Transaction();
//系統獎勵給我們的交易
Transaction sysTransaction = new Transaction();
List<Transaction> transactionList = new ArrayList<>();
transactionList.add(transaction1);
transactionList.add(transaction2);
transactionList.add(sysTransaction);
//設置隨機數
int nonce = 1;
//得到前一個區塊
Block previousBlock = blockChain.get(blockChain.size() - 1);
//第一次計算
//區塊的哈希值 = 上一個區塊的哈希值 + 交易信息 + 隨機數
String hash = SHA256(previousBlock.getHash() + JSON.toJSONString(transactionList) + nonce);
//不滿足條件,重複計算,直到條件滿足爲止
while (!hash.startsWith("000")){
nonce++;
hash = SHA256(JSON.toJSONString(transactionList) + previousBlock.getHash()+nonce);
}
//爲新產生的區塊填充信息
Block newBlock = Block.builder()
.previousHash(previousBlock.getHash())
.hash(hash)
.nonce(nonce)
.transactions(transactionList)
.timeStamp(System.currentTimeMillis())
.index(previousBlock.getIndex() + 1)
.build();
//填充信息之後加到區塊鏈中
blockChain.add(newBlock);
return newBlock;
}
下面再說下代碼中大家可能存在不解的地方 :
-
JSON.toJSONString
用到了Alibaba
的fastjson
這裏給出相關的pom.xml配置
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.51</version> </dependency>
-
blockChain
這通過名字不難看出就是區塊鏈,上一篇文章我們有所提到,大家現在可以就認爲區塊鏈剛剛生成,裏面只有創世區塊。List<Block> blockChain = new ArrayList<>(); blockChain.add(firstBlock);
-
關於哈希算法,我們不做具體說明,大家感興趣的話可以深入研究。那麼這裏使用到了SHA256的哈希算法,大家也可自行百度java的實現版本,在下面給出我的代碼(其實也是照搬的)
public static String SHA256(String str){ MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(str.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (Exception e) { e.printStackTrace(); } return encodeStr; } private static String byte2Hex(byte[] bytes){ String strHex = ""; StringBuilder sb = new StringBuilder(""); for (int n = 0; n < bytes.length; n++) { strHex = Integer.toHexString(bytes[n] & 0xFF); sb.append((strHex.length() == 1) ? "0" + strHex : strHex); } return sb.toString().trim(); }
至此,我們已經初步瞭解了挖礦的流程,對於代碼中的交易集合,之前並沒有提到,所以,在下一篇文章中,會對它做一個詳細的介紹。
歡迎去看下一篇文章:編程小白模擬簡易比特幣系統(三)