1. 程式人生 > >區塊鏈-java入門Demo

區塊鏈-java入門Demo

正在建立第一個區塊鏈....... 
建立區塊:00000d3c0681cd67f8050ab996e1400f99c0060ba4cb22d0c07685d9ae50cd10
正在建立第二個區塊鏈....... 
建立區塊:00000eafdd53bed5586d480d7704169c45b25fcb0bc5846b16be6fbeee88ec69
正在建立第三個區塊鏈.......
建立區塊:00000a6391f185b143bfccf571ef660204f945f43cb4101e804b360d06c9af66
區塊鏈是否有效的: true
[
  {
    "hash": "00000d3c0681cd67f8050ab996e1400f99c0060ba4cb22d0c07685d9ae50cd10",
    "previousHash": "0",
    "data": "我是第一個區塊鏈",
    "timeStamp": 1528268281634,
    "nonce": 7033501
  },
  {
    "hash": "00000eafdd53bed5586d480d7704169c45b25fcb0bc5846b16be6fbeee88ec69",
    "previousHash": "00000d3c0681cd67f8050ab996e1400f99c0060ba4cb22d0c07685d9ae50cd10",
    "data": "我是第二個區塊鏈",
    "timeStamp": 1528268301568,
    "nonce": 340676
  },
  {
    "hash": "00000a6391f185b143bfccf571ef660204f945f43cb4101e804b360d06c9af66",
    "previousHash": "00000eafdd53bed5586d480d7704169c45b25fcb0bc5846b16be6fbeee88ec69",
    "data": "我是第三個區塊鏈",
    "timeStamp": 1528268302664,
    "nonce": 319404
  }
]

Process finished with exit code 0

1.Block

package com.block;
import java.util.Date;

/**
 * @Author: cxx
 * 封裝區塊物件
 * @Date: 2018/6/6 14:45
 */
public class Block {
    public String hash;
    //上一個區塊的hash值
    public String previousHash;
    //每個區塊存放的資訊,這裡我們存放的是一串字串
    private String data;
    //時間戳
    private long timeStamp;
    //挖礦者的工作量證明
    private int nonce;

    //構造
    public Block(String data,String previousHash ) {
        this.data = data;
        this.previousHash = previousHash;
        this.timeStamp = new Date().getTime();
        //根據previousHash、data和timeStamp產生唯一hash
        this.hash = calculateHash();
    }

    //基於上一塊的內容計算新的雜湊
    public String calculateHash() {
        String calculatedhash = StringUtil.applySha256(
                previousHash +
                        Long.toString(timeStamp) +
                        Integer.toString(nonce) +
                        data
        );
        return calculatedhash;
    }

    //挖礦
    public void mineBlock(int difficulty) {
        //目標值,difficulty越大,下面計算量越大
        String target = StringUtil.getDificultyString(difficulty);
        //difficulty如果為5,那麼target則為 00000
        while(!hash.substring( 0, difficulty).equals(target)) {
            nonce ++;
            hash = calculateHash();
        }
        System.out.println("建立區塊:" + hash);
    }
}

2.StringUtil

package com.block;
import java.security.MessageDigest;
import com.google.gson.GsonBuilder;
/**
 * 工具類
 * 建立數字簽名、返回JSON格式資料、返回難度字串目標
 * @author pibigstar
 *
 */
public class StringUtil {

    //將Sha256應用到一個字串並返回結果
    public static String applySha256(String input){
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes("UTF-8"));
            StringBuffer hexString = new StringBuffer();
            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);
        }
    }

    //返回JSON格式資料
    public static String getJson(Object o) {
        return new GsonBuilder().setPrettyPrinting().create().toJson(o);
    }

    //返回難度字串目標,與雜湊比較。難度5將返回“00000”
    public static String getDificultyString(int difficulty) {
        return new String(new char[difficulty]).replace('\0', '0');
    }

    public static void main(String[] args) {
        System.out.println(getDificultyString(5));
    }


}

3.BlockChain

package com.block;
import java.util.ArrayList;
import com.google.gson.GsonBuilder;
/**
 * 建立區塊鏈
 * @author pibigstar
 *
 */
public class BlockChain{
    //存放所有的區塊集合
    public static ArrayList<Block> blockchain = new ArrayList<Block>();
    public static int difficulty = 5;//挖礦的難度,數字越大越難

    public static void main(String[] args) {
        System.out.println("正在建立第一個區塊鏈....... ");
        addBlock(new Block("我是第一個區塊鏈", "0"));//創世塊

        System.out.println("正在建立第二個區塊鏈....... ");
        addBlock(new Block("我是第二個區塊鏈",blockchain.get(blockchain.size()-1).hash));

        System.out.println("正在建立第三個區塊鏈.......");
        addBlock(new Block("我是第三個區塊鏈",blockchain.get(blockchain.size()-1).hash));

        System.out.println("區塊鏈是否有效的: " + isChainValid());

        String blockchainJson = StringUtil.getJson(blockchain);
        System.out.println(blockchainJson);
    }

    /**
     * 檢查區塊鏈的完整性
     * @return
     */
    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.previousHash) ) {
                System.out.println("Previous Hashes not equal");
                return false;
            }
            //檢查雜湊是否被使用
            if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) {
                System.out.println("這個區塊還沒有被開採。。。");
                return false;
            }

        }
        return true;
    }
    /**
     * 增加一個新的區塊
     * @param newBlock
     */
    public static void addBlock(Block newBlock) {
        newBlock.mineBlock(difficulty);
        blockchain.add(newBlock);
    }
}