作者注: 写了一个 ParallelBFT.java 应用到我们的项目中,从交易验证到投票机制,从合约执行到区块上链。当然,区块链还有很多部分,介绍不完,因此简单介绍一下重要的代码部分。
背景设定:我们想模拟什么?
在区块链世界,节点之间如何达成“某个区块是合法的”,这就是共识协议要解决的问题。
这段代码实现了一个轻量化的共识流程,模拟了类似 PBFT 的流程,简化为:
预准备(pre_prepare)→ 准备(prepare)→ 提交(commit)→ 同步(sync)
它还带有一种“测试模型”的味道,忽略了签名验证失败和合约执行失败,让我们能聚焦在流程本身。
模块一:启动共识 —— startConsensus
共识的起点,是 startConsensus 方法。
它做了什么?
验证交易签名(可以忽略失败)
构造区块头 + 区块体
设置前一个区块 Hash(Genesis / 最新区块)
打包为 P2PMessage,广播出去(类型是 \”pre_prepare\”)
这相当于在共识会议上,提议人挥了挥手说:
“各位,我有一个新块建议,请开始讨论!”
public String startConsensus(consensusTxSet txSet, Map<String, RSAKeyPair> keyStorage) throws Exception {
int totalTxNumber=txSet.getTxlist().size();
if(EXPER_MODEL== \”simple\”){
TransactionVerify tv=new TransactionVerify();
try{
if(tv.sigVerify(txSet,keyStorage)==false){
System.out.println(\”测试模式,忽略验签失败\”);
//return \”txSigVerify_false\”;
}
}catch(NullPointerException e){
System.out.println(\”测试模式,忽略验签exception\”);
}
hashCreat hc=new hashCreat();
blockHeader bh=new blockHeader();
blockBody bb=new blockBody();
bb.setCtxset(txSet);
bh.setBlockBodyHash(hc.hashSHA_256(new ObjectMapper().writeValueAsString(bb)));
bh.setBlockTxSize(totalTxNumber);
//bh.setBlockSize((int) RamUsageEstimator.sizeOf(bb));
if(!simpleBlockchain.blockHashList.isEmpty()){
bh.setPre_blockTotalHash(simpleBlockchain.blockHashList.get(simpleBlockchain.blockHashList.size()-1));
}else {
bh.setPre_blockTotalHash(\”Genesis\”);
}
bh.setBlockTotalHash(hc.hashSHA_256(new ObjectMapper().writeValueAsString(bh)));
block b=new block();
b.setBlockbody(bb);
b.setBlockheader(bh);
//System.out.println(\”2\”);
P2PMessage pm=new P2PMessage();
pm.setNetAddress(NodeList.local);
//System.out.println(\”3\”);
pm.setMessageType(\”pre_prepare\”);
Date currentDate = new Date(); // 获取当前时间
SimpleDateFormat sdf = new SimpleDateFormat(\”yyyy-MM-dd HH:mm:ss.SSS\”); // 指定日期格式
String formattedDate = sdf.format(currentDate); // 格式化日期为指定格式
pm.setMessageTime(formattedDate.toString());
pm.setSig(NodeList.localsig);
pm.setMessage(new ObjectMapper().writeValueAsString(b));
P2PBroadcasting p2pb=new P2PBroadcasting();
System.out.println(p2pb.springbootRpcBroadcasting(pm));
}
return \”\”;
}
模块二:预准备阶段 —— pre_Prepare
其他节点一收到 \”pre_prepare\” 消息,就马上转发 \”prepare\” 消息。
这一步相当于说:
public String pre_Prepare(P2PMessage pm) throws IOException {
if(EXPER_MODEL== \”simple\”){
//System.out.println(\”收到pre_prepare消息,广播prepare消息\”);
P2PMessage pm2=new P2PMessage();
pm2.setNetAddress(NodeList.local);
pm2.setMessageType(\”prepare\”);
Date currentDate = new Date(); // 获取当前时间
SimpleDateFormat sdf = new SimpleDateFormat(\”yyyy-MM-dd HH:mm:ss.SSS\”); // 指定日期格式
String formattedDate = sdf.form

