編程小白模擬簡易比特幣系統(二)


在上一篇文章 :編程小白模擬簡易比特幣系統(一)中,我們明白了區塊和區塊鏈的概念,創建了創世區塊,同時也留下了兩個問題:

區塊結構中,工作量證明是什麼?第二個區塊是怎麼來的?

那麼請大家繼續往下看👇

相關概念

挖礦⛏是什麼?

挖礦這個詞想必大家早已聽聞,但一直不太清楚到底是在幹什麼,也許會知道計算機在不停的計算,那我就基於個人的理解給大家分享一下:

上回書我們談到區塊鏈是由區塊一塊一塊連接得到的,那麼到底是誰有權利去決定下一個區塊是什麼呢?也就是說在這個有我們所有人的交易記錄的大賬本中,是誰去記錄下一頁呢?這就引出了我們挖礦的概念。

mine

每個區塊的產生都需要所有人去解決一個數學難題,誰可以答上來,誰就有權利。前面提到,區塊中有一個信息是當前區塊的hash值它就是這個數學難題的答案。哈希值我們都知道,就是一個字符串。大家可能想,計算一個字符串有什麼難的,我的電腦分分鐘千萬個Hello world!

那麼大家可不要小瞧這個難題的工作量!計算符合一定條件限制的hash需要耗費大量的算力,比特幣目前規定的hash要求是十多個零開頭,我們的個人筆記本電腦可能得算個幾年幾十年的。

至此,解決了這個難題就獲得了記賬的權利,但是耗費如此大的算力去計算這個難題,僅僅只獲得記賬的權利是不是太虧了?所以系統還會分發給難題解決者一部分比特幣作爲獎勵這個計算的過程,被形象的稱爲挖礦。

工作量證明是什麼?

細心的朋友應該已經發現上面挖礦過程中,我已經提到了工作量,沒錯,工作量就是整個計算過程耗費的算力。上篇文章講過:

區塊的哈希值 = 上一個區塊的哈希值+ 交易信息 + 隨機數

那麼對於這個球球幣系統來說,隨機數可以從1開始遞增,直到達到要求的hash,隨機數就代表了計算的次數,我們可以簡單的把它當作我們的工作量證明

第二個區塊是怎麼來的?

解決了數學難題,因此獲得了記賬的權利,所以有權利去補充下一頁賬本了,也就是新區塊要生成了

在求解數學難題的時候,也許期間會發生許多交易。因此,我們需要把發生的交易記錄下來,這裏注意,我們剛剛挖礦的時候,系統也獎勵了我們一筆球球幣這也是一筆交易,所以我們在記賬的時候同樣需要記錄

那麼挖礦的大致流程就可以理解爲:

mine

說了這麼多,相信各位對這些概念似懂非懂,不過沒關係,還是落實到代碼上來的實在一點👇

相關僞代碼

對照上面的流程圖,我們不難寫出這樣的代碼。那麼關於交易,我們暫時先把它當成一個普通的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;
}

下面再說下代碼中大家可能存在不解的地方 :

  1. JSON.toJSONString用到了Alibabafastjson

    這裏給出相關的pom.xml配置

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.51</version>
    </dependency>
    
  2. blockChain這通過名字不難看出就是區塊鏈,上一篇文章我們有所提到,大家現在可以就認爲區塊鏈剛剛生成,裏面只有創世區塊

    List<Block> blockChain = new ArrayList<>();
    blockChain.add(firstBlock);
    
  3. 關於哈希算法,我們不做具體說明,大家感興趣的話可以深入研究。那麼這裏使用到了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();
        }
    

至此,我們已經初步瞭解了挖礦的流程,對於代碼中的交易集合,之前並沒有提到,所以,在下一篇文章中,會對它做一個詳細的介紹。

歡迎去看下一篇文章:編程小白模擬簡易比特幣系統(三)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章