区块Hash值计算公式:
Hash=SHA256(最后一个区块的Hash+交易信息+随机数)
(2)Block代码
package com.blockchain.model;
import java.util.List;
/**
* 区块结构
*/
public class Block {
/**
* 区块索引号
*/
private int index;
/**
* 当前区块的hash值,区块唯一标识
*/
private String hash;
/**
* 生成区块的时间戳
*/
private long timestamp;
/**
* 当前区块的交易集合
*/
private List transactions;
/**
* 工作量证明,计算正确hash值的次数
*/
private int nonce;
/**
* 前一个区块的hash值
*/
private String preHash;
public Block() {
super();
}
public Block(int index, long timestamp, List transactions, int nonce, String preHash, String hash) {
super();
this.index = index;
this.timestamp = timestamp;
this.transactions = transactions;
this.nonce = nonce;
this.preHash = preHash;
this.hash = hash;
}
//省略getter和setter
}
(1)挖矿流程
(2)挖矿测试代码
package com.blockchain.block;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.alibaba.fastjson.JSON;
import com.blockchain.model.Block;
import com.blockchain.model.Transaction;
import com.blockchain.model.TransactionInput;
import com.blockchain.model.TransactionOutput;
import com.blockchain.model.Wallet;
import com.blockchain.security.CryptoUtil;
/**
* 区块链测试
*/
public class BlockServiceTest {
@Before
public void setUp() throws Exception {
}
@Test
public void testBlockMine() throws Exception {
//创建一个空的区块链
List blockchain = new ArrayList<>();
//生成创世区块,空交易
Block block = new Block(1,System.currentTimeMillis(),new ArrayList(),1,"","1");
//加入创世区块到区块链里
blockchain.add(block);
System.out.println("初始化区块链:\n"+JSON.toJSONString(blockchain));
//上一区块到现在发生的交易
Transaction tx1 = new Transaction();
Transaction tx2 = new Transaction();
Transaction tx3 = new Transaction();
//交易打包
List txs = new ArrayList<>();
txs.add(tx1);
txs.add(tx2);
txs.add(tx3);
//加入系统奖励的交易
Transaction sysTx = new Transaction();
txs.add(sysTx);
//获取当前区块链里的最后一个区块
Block last = blockchain.get(blockchain.size() - 1);
//随机数开始值
int nonce = 1;
String hash = "";
long start=System.currentTimeMillis();
while(true){
//计算新的Hash值
hash = CryptoUtil.sha256(last.getHash()+JSON.toJSONString(txs) + nonce);
if (hash.startsWith("0000")) {//验证新Hash值是否正确
break;
}
nonce++;
}
System.out.println("=====计算结果正确,计算次数为:" +nonce+ ",hash:" + hash);
System.out.println("耗时毫秒数:"+(System.currentTimeMillis()-start));
//构造新区块
Block newBlock=new Block(last.getIndex()+1,System.currentTimeMillis(),txs,nonce,last.getHash(),hash);
//新区块加入区块链最后
blockchain.add(newBlock);
System.out.println("挖矿后的区块链:" + JSON.toJSONString(blockchain));
}
}
运行测试样例:Run as –> Junit Test
初始化区块链:
[{"hash":"1","index":1,"nonce":1,"preHash":"","timestamp":1521731140922,"transactions":[]}]
=====计算结果正确,计算次数为:96507,hash:0000c189d48cdd6f0fcd965f6323f6da97f86534d52863e0f4aa90cd23bf700b
耗时毫秒数:613
挖矿后的区块链:[{"hash":"1","index":1,"nonce":1,"timestamp":1521731140922,"transactions":[]},{"hash":"0000c189d48cdd6f0fcd965f6323f6da97f86534d52863e0f4aa90cd23bf700b","index":2,"nonce":96507,"preHash":"1","timestamp":1521731141808,"transactions":[{},{},{},{}]}]
很显然,一个创世区块,一个新区块(其中4个空交易记录)。