pom文件:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<!-- 加密包 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
</dependencies>
测试类:
package indi.laf.blockchain;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
BlockChain bc=new BlockChain();
for (int i = 0; i < 5; i++) {
bc.append(i+"");
}
bc.print();
//挖矿
bc.mineBlock(5);
}
}
区块类:
package indi.laf.blockchain;
public class Block {
/** 是这个块在整个链中的位置 */
private int index;
/** 显而易见就是块生成时的时间戳 */
private String timestamp;
/** 我们要记录的数据 */
private String data;
/** 是这个块通过 SHA256 算法生成的散列值 */
private String hash;
/** 指向前一个块的 SHA256 散列值 */
private String prevHash;
//工作量(挖的次数)
private int nonce;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public String getPrevHash() {
return prevHash;
}
public void setPrevHash(String prevHash) {
this.prevHash = prevHash;
}
public int getNonce() {
return nonce;
}
public void setNonce(int nonce) {
this.nonce = nonce;
}
}
区块链类:
package indi.laf.blockchain;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.apache.commons.codec.digest.DigestUtils;
import com.google.gson.Gson;
public class BlockChain {
ArrayList<Block> bc = new ArrayList<Block>();
Gson gs=new Gson();
public String calculateHash(Block block) {
String record = block.getNonce()+block.getIndex() + block.getTimestamp() + (block.getData()) + block.getPrevHash();
return DigestUtils.sha256Hex(record);
}
// 生成一个区块
public Block generateBlock(String data) {
Block newBlock = new Block();
newBlock.setIndex(bc.size());
newBlock.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
newBlock.setData(data);
newBlock.setPrevHash(bc.size() == 0 ? "" : bc.get(bc.size() - 1).getHash());
newBlock.setHash(calculateHash(newBlock));
return newBlock;
}
// 校验
public boolean isBlockValid(Block newBlock) {
int lastIndex = newBlock.getIndex() - 1;
// 第一个的情况
if (lastIndex == -1) {
return true;
}
Block oldBlock = bc.get(lastIndex);
if (oldBlock.getIndex() != newBlock.getIndex() - 1) {
return false;
}
if (!oldBlock.getHash().equals(newBlock.getPrevHash())) {
return false;
}
if (!calculateHash(newBlock).equals(newBlock.getHash())) {
return false;
}
return true;
}
public void append(String data) {
Block newBlock = generateBlock(data);
if (isBlockValid(newBlock)) {
bc.add(newBlock);
}
}
// 过期的链切换成最新的链
public void replaceChain(ArrayList<Block> newBlocks) {
if (newBlocks.size() > bc.size()) {
bc = newBlocks;
}
}
//挖矿
public void mineBlock(int difficulty) {
Block block = bc.get(bc.size()-1);
String target = new String(new char[difficulty]).replace('\0', '0');
while (!block.getHash().substring(0, difficulty).equals(target)) {
block.setNonce(block.getNonce()+1);
block.setHash(calculateHash(block));
}
System.out.println("挖到矿了!!!" + block.getHash()+",挖了"+block.getNonce()+"次");
}
//遍历打印
public void print() {
for (Block block : bc) {
System.out.println(gs.toJson(block));
}
}
}