跟着网上的教程用java实现了个简易的区块链,真正的比特币之类应该是加入了一万个细节:)
主要根据以下几篇文章学习:
代码如下(最后输出的是json格式,需要下个gson的jar包导入)
定义区块类
import java.util.Date;
public class Block {
public String 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();
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) {
//需要根据hash值前几位的0的数量来做工作量证明
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);
}
}
封装SHA256算法
import java.security.MessageDigest;
public class StringUtil {
//只需要知道这个函数能应用sha256算法,返回一个hash值
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);
}
}
}
主程序
import java.util.ArrayList;
import com.google.gson.GsonBuilder; //需要下个gson的jar包导入
public class NoobChain {
public static ArrayList<Block> blockchain = new ArrayList<Block>(); //动态数组装区块
public static int difficulty = 5; //难度值设定
public static void main(String[] args) {
blockchain.add(new Block("Hi im the first block", "0")); //加入个区块也不代表是被承认的区块
System.out.println("Trying to Mine block 1... ");
blockchain.get(0).mineBlock(difficulty); //经过挖矿操作,得到被承认的区块
blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash));
System.out.println("Trying to Mine block 2... ");
blockchain.get(1).mineBlock(difficulty);
blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash));
System.out.println("Trying to Mine block 3... ");
blockchain.get(2).mineBlock(difficulty);
System.out.println("\nBlockchain is Valid: " + isChainValid());
String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain);
System.out.println("\nThe block chain: ");
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);
//检查当前区块hash值
if(!currentBlock.hash.equals(currentBlock.calculateHash()) ){
System.out.println("Current Hashes not equal");
return false;
}
//检查当前区块的previousHash值
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("This block hasn't been mined");
return false;
}
}
return true;
}
}
输出结果
Blockchain is Valid: true
The block chain:
[
{
"hash": "00000d90c888bedcf24e46e3753afb5fdcb956d34c3d4edf8bec969f3fcc4548",
"previousHash": "0",
"data": "Hi im the first block",
"timeStamp": 1581343301486,
"nonce": 1598747
},
{
"hash": "000006607ab6534596f388cc88709c7dabab8dfd4ce1436cb8e91192e5bdd2bf",
"previousHash": "00000d90c888bedcf24e46e3753afb5fdcb956d34c3d4edf8bec969f3fcc4548",
"data": "Yo im the second block",
"timeStamp": 1581343305531,
"nonce": 416510
},
{
"hash": "000006319344772c1f2f8b42691dce889a08d44194017443493118004252965e",
"previousHash": "000006607ab6534596f388cc88709c7dabab8dfd4ce1436cb8e91192e5bdd2bf",
"data": "Hey im the third block",
"timeStamp": 1581343306307,
"nonce": 2320874
}
]