创建一个maven项目 pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.blockchain.block</groupId>
<artifactId>blockchain</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.blockchain.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>blockchain</finalName>
<defaultGoal>compile</defaultGoal>
</build>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
</project>
创建二个实体类: Block
package com.blockchain.model;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.blockchain.security.CryptoUtil;
/**
* 区块结构
* @author zhiwei liao
*
*/
public class Block {
/**
* 区块索引号
*/
private int index;
/**
* 当前区块的hash值,区块唯一标识
*/
private String hash;
/**
* 生成区块的时间戳
*/
private long timestamp;
/**
* 当前区块的交易集合
*/
private List<Transaction> transactions;
/**
* 工作量证明,计算正确hash值的次数
*/
private int nonce;
/**
* 前一个区块的hash值
*/
private String previousHash;
public Block() {
super();
}
public Block(int index, long timestamp, List<Transaction> transactions, int nonce, String previousHash, String hash) {
super();
this.index = index;
this.timestamp = timestamp;
this.transactions = transactions;
this.nonce = nonce;
this.previousHash = previousHash;
this.hash = hash;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
public int getNonce() {
return nonce;
}
public void setNonce(int nonce) {
this.nonce = nonce;
}
public String getPreviousHash() {
return previousHash;
}
public void setPreviousHash(String previousHash) {
this.previousHash = previousHash;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
/**
* 挖矿
* @param blockchain 整个区块链
* @param txs 需记账交易记录
* @param address 矿工钱包地址
* @return
*/
public static void mineBlock(List<Block> blockchain, List<Transaction> txs, String address) {
//加入系统奖励的交易
Transaction sysTx = new Transaction(CryptoUtil.UUID(), "", address, 10);
txs.add(sysTx);
//获取当前区块链里的最后一个区块
Block latestBlock = blockchain.get(blockchain.size() - 1);
//随机数
int nonce = 1;
String hash = "";
while(true){
hash = CryptoUtil.SHA256(latestBlock.getHash() + JSON.toJSONString(txs) + nonce);
if (hash.startsWith("0000")) {
System.out.println("=====计算结果正确,计算次数为:" +nonce+ ",hash:" + hash);
break;
}
nonce++;
System.out.println("计算错误,hash:" + hash);
}
//解出难题,可以构造新区块并加入进区块链里
Block newBlock = new Block(latestBlock.getIndex() + 1, System.currentTimeMillis(), txs, nonce, latestBlock.getHash(), hash);
blockchain.add(newBlock);
System.out.println("挖矿后的区块链:" + JSON.toJSONString(blockchain));
}
}
Transaction
package com.blockchain.model;
/**
* 交易
* @author zhiwei liao
*/
public class Transaction {
/**
* 交易唯一标识
*/
private String id;
/**
* 交易发送方
*/
private String sender;
/**
* 交易接收方
*/
private String recipient;
/**
* 交易金额
*/
private int amount;
public Transaction() {
super();
}
public Transaction(String id, String sender, String recipient, int amount) {
super();
this.id = id;
this.sender = sender;
this.recipient = recipient;
this.amount = amount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Transaction other = (Transaction) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
加密工具类
package com.blockchain.security;
import java.security.MessageDigest;
import java.util.UUID;
/**
* 加密工具类
*
* @author zhiwei liao
*
*/
public class CryptoUtil {
private CryptoUtil() {
}
public static String SHA256(String str) {
MessageDigest messageDigest;
String encodeStr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(str.getBytes("UTF-8"));
encodeStr = byte2Hex(messageDigest.digest());
} catch (Exception e) {
System.out.println("getSHA256 is error" + e.getMessage());
}
return encodeStr;
}
public static String UUID() {
return UUID.randomUUID().toString().replaceAll("\\-", "");
}
private static String byte2Hex(byte[] bytes) {
StringBuilder builder = new StringBuilder();
String temp;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
builder.append("0");
}
builder.append(temp);
}
return builder.toString();
}
}
Main方法执行:
package com.blockchain;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.blockchain.model.Block;
import com.blockchain.model.Transaction;
import com.blockchain.security.CryptoUtil;
/**
* 交易
* @author zhiwei liao
*/
public class Main {
public static void main(String[] args) {
//创建一个空的区块链
List<Block> blockchain = new ArrayList<>();
//生成创世区块
Block block = new Block(1, System.currentTimeMillis(), new ArrayList<Transaction>(), 1, "1", "1");
//加入创世区块到区块链里
blockchain.add(block);
System.out.println(JSON.toJSONString(blockchain));
// 发送方钱包地址
String sender = "sender_wallet";
//接收方钱包地址
String recipient = "recipient_wallet";
//创建一个空的交易集合
List<Transaction> txs = new ArrayList<>();
//挖矿
Block.mineBlock(blockchain, txs, sender);
System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
//创建一个空的交易集合
List<Transaction> txs1 = new ArrayList<>();
//已发生但未记账的交易记录,发送者给接收者转账3个比特币
Transaction tx1 = new Transaction(CryptoUtil.UUID(), sender, recipient, 3);
//已发生但未记账的交易记录,发送者给接收者转账1个比特币
Transaction tx2 = new Transaction(CryptoUtil.UUID(), sender, recipient, 1);
txs1.add(tx1);
txs1.add(tx2);
//挖矿
Block.mineBlock(blockchain, txs1, sender);
System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
System.out.println(recipient + "钱包的余额为:" + getWalletBalance(blockchain, recipient));
}
/**
* 查询余额
* @param blockchain
* @param address
* @return
*/
public static int getWalletBalance(List<Block> blockchain, String address) {
int balance = 0;
for (Block block : blockchain) {
List<Transaction> transactions = block.getTransactions();
for (Transaction transaction : transactions) {
if (address.equals(transaction.getRecipient())) {
balance += transaction.getAmount();
}
if (address.equals(transaction.getSender())) {
balance -= transaction.getAmount();
}
}
}
return balance;
}
}
这样一个简单的比特币系统就做好啦