用Java編寫第一個區塊鏈

來源:互聯網
上載者:User

標籤:ret   boolean   判斷   包含   current   inpu   運算   Once   ali   

原文地址:https://www.cnblogs.com/zacky31/p/9057193.html

目標:

  • 建立一個最基本的“區塊鏈”
  • 實現一個簡單的挖礦系統

前提:

  對物件導向編程有一定的基礎

注意:

  值得注意的是,這不會是一個完整的功能,恰恰相反,這是一個概念證明的執行個體,可以協助您進一步瞭解區塊鏈。

準備:

  我將會使用Java來實現,當然你也可以使用任何物件導向的語言。

環境:

  • JDK 8
  • IDEA
  • Maven

開始吧

  區塊鏈就好比多個塊串連起來。其中每一塊都將擁有自己的簽名,簽名中包含其前面的塊資訊和一些資料(例如交易資訊)。

  每個塊不僅僅包含它之前的塊資訊,同時也包含自身。如果前面一塊內容改變了,其 hash 值也會改變,將會導致其後面所有的塊發生變化。通過計算和比較所得的 hash 值,我們可以判斷區塊鏈是否合法。換句話說,改變區塊鏈中的任意內容,將會改變整個區塊鏈的簽名。

  根據上面的分析,我們先建立一個 Block 類。

import java.util.Date;public class Block {    public String hash; //存放數位簽章    public String preHash; //前面塊的簽名    private String data;    private long timeStamp;    public Block(String data, String preHash) {        this.data = data;        this.preHash = preHash;        this.timeStamp = new Date().getTime();    }}

  接下來,我們需要一個產生簽名的方法。有很多密碼編譯演算法可供選擇,這裡使用 SHA256 剛剛好。

 

import java.security.MessageDigest;public class StringUtil {    public static String applySha256(String input) {        try {            MessageDigest digest = MessageDigest.getInstance("SHA-256");            byte[] hash = digest.digest(input.getBytes("UTF-8"));            StringBuilder hexString = new StringBuilder();            for (int i = 0; i < hash.length; i++) {                String hex = Integer.toHexString(0xff & hash[i]);                if (hex.length() == 1) hexString.append(‘0‘);                hexString.append(hex);            }            return hexString.toString();        } catch (Exception e) {            throw new RuntimeException(e);        }    }}

 

  現在,我們向 Block 類中添加計算數位簽章的方法,並修改一下其構造方法。

public Block(String data, String preHash) {        this.data = data;        this.preHash = preHash;        this.timeStamp = new Date().getTime();        this.hash = calculateHash();    }    public String calculateHash() {        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) + data);        return calculatedhash;    }

  到這裡,可以寫個 Main 方法看一下效果。

public class Main {    public static void main(String[] args) {        Block first = new Block("Hi i am the first block", "0");        System.out.println("Hash for block 1 : " + first.hash);        Block second = new Block("Hi i am the second block", first.hash);        System.out.println("Hash for block 2 : " + second.hash);        Block third = new Block("Hi i am the third block", second.hash);        System.out.println("Hash for block 3 : " + third.hash);    }}

  可以看見每個 Block 都有自己唯一的 數位簽章,當然,現在還沒有構成一個區塊鏈,將這些塊存放到一個 ArrayList 中吧。修改 Main 類後再次運行。

import com.google.gson.GsonBuilder;import java.util.ArrayList;public class Main {    public static ArrayList<Block> blockchain = new ArrayList<Block>();    public static void main(String[] args) {        blockchain.add(new Block("Hi i am the first block", "0"));        blockchain.add(new Block("Hi i am the second block", blockchain.get(blockchain.size() - 1).hash));        blockchain.add(new Block("Hi i am the third block", blockchain.get(blockchain.size() - 1).hash));        String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);        System.out.println(blockchainJson);    }}

  現在,需要一種方法去驗證建立的區塊鏈。編寫一段 isChainValid() 方法。任何塊的改變將會導致這個方法失效。

public static Boolean isChainValid() {        Block currentBlock;        Block previousBlock;        for (int i = 1; i < blockchain.size(); i++) {            currentBlock = blockchain.get(i);            previousBlock = blockchain.get(i - 1);            if (!currentBlock.hash.equals(currentBlock.calculateHash())) {                System.out.println("Current Hashes not equal!");                return false;            }            if (!previousBlock.hash.equals(currentBlock.preHash)) {                System.out.println("Previous Hashes not equal!");                return false            }        }        return true;    }

  接下來,嘗試一下挖礦!

  

  在 Block 類中,新增一個變數 nonce,並且添加到 calculateHash() 這個方法中,同時需要 mineBlock() 這個方法。這個方法中的 difficulty 變數就是用來控制計算量的。當設定的值較低時,大部分電腦很快就能算出來。

import java.util.Date;public class Block {    public String hash;    public String preHash;    private String data;    private long timeStamp;    private int nonce;    public Block(String data, String preHash) {        this.data = data;        this.preHash = preHash;        this.timeStamp = new Date().getTime();        this.hash = calculateHash();    }    public String calculateHash() {        String calculatedhash = StringUtil.applySha256(preHash + Long.toString(timeStamp) + Integer.toString(nonce) +                data);        return calculatedhash;    }    public void mineBlock(int difficulty) {        String target = new String(new char[difficulty]).replace(‘\0‘, ‘0‘);        while (!hash.substring(0, difficulty).equals(target)) {            nonce++;            hash = calculateHash();        }        System.out.println("Block Mined!!!" + hash);    }}

  我們可以在 Main 類中定義個靜態變數。嘗試在每次建立新塊去調用 mineBlock() 方法。

import com.google.gson.GsonBuilder;import java.util.ArrayList;import java.util.Date;public class Main {    public static ArrayList<Block> blockchain = new ArrayList<Block>();    public static int difficulty = 5;    public static void main(String[] args) {        long beginTime1 = new Date().getTime();        blockchain.add(new Block("Hi i am the first block", "0"));        System.out.println("Trying to  mine block 1...");        blockchain.get(0).mineBlock(difficulty);        long endTime1 = new Date().getTime();        System.out.println("Mining block 1 cost " + (endTime1 - beginTime1));        long beginTime2 = new Date().getTime();        blockchain.add(new Block("Hi i am the second block", blockchain.get(blockchain.size() - 1).hash));        System.out.println("Trying to  mine block 2...");        blockchain.get(1).mineBlock(difficulty);        long endTime2 = new Date().getTime();        System.out.println("Mining block 1 cost " + (endTime2 - beginTime2));        long beginTime3 = new Date().getTime();        blockchain.add(new Block("Hi i am the third block", blockchain.get(blockchain.size() - 1).hash));        System.out.println("Trying to  mine block 3...");        blockchain.get(2).mineBlock(difficulty);        long endTime3 = new Date().getTime();        System.out.println("Mining block 1 cost " + (endTime3 - beginTime3));        System.out.println("\nBlockchain is Valid: " + isChainValid());        String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);        System.out.println(blockchainJson);    }    public static Boolean isChainValid() {        Block currentBlock;        Block previousBlock;        String hashTarget = new String(new char[difficulty]).replace(‘\0‘, ‘0‘);        for (int i = 1; i < blockchain.size(); i++) {            currentBlock = blockchain.get(i);            previousBlock = blockchain.get(i - 1);            if (!currentBlock.hash.equals(currentBlock.calculateHash())) {                System.out.println("Current Hashes not equal!");                return false;            }            if (!previousBlock.hash.equals(currentBlock.preHash)) {                System.out.println("Previous Hashes not equal!");                return false;            }            if (!currentBlock.hash.substring(0, difficulty).equals(hashTarget)) {                System.out.println("This block hasn‘t been mined");                return false;            }        }        return true;    }}

  運行發現,挖礦過程還是很費時間的。把計算量改成7,差不多每挖一個需要一分鐘。。。

  如果在此過程中,有人篡改了資料,將會導致:

  • 區塊鏈將會無效
  • 不能夠建立一個更長的區塊鏈
  • 網路中的誠實鏈將會比較長的區塊鏈有時間上的優勢

  不過如果篡改資料擁有更強的運算速度,可能成功篡改。

  這樣,基本上簡單實現了一個區塊鏈了。

用Java編寫第一個區塊鏈

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.