正在创建第一个区块链....... 创建区块: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); } }