diff --git a/src/main/java/com/mindata/blockchain/block/check/BlockChecker.java b/src/main/java/com/mindata/blockchain/block/check/BlockChecker.java index a33ef3f93f605d0dc8e3b4ef49471919f7e3c62c..44fbd5af3f2c690d862688e296396162ae935ce7 100644 --- a/src/main/java/com/mindata/blockchain/block/check/BlockChecker.java +++ b/src/main/java/com/mindata/blockchain/block/check/BlockChecker.java @@ -40,4 +40,19 @@ public interface BlockChecker { * @return block */ int checkTime(Block block); + + /** + * 校验签名 + * @param block block + * @return block + */ + int checkSign(Block block); + + /** + * 校验block,包括签名、hash、关联关系 + * @param block + * @return + */ + public String checkBlock(Block block); + } diff --git a/src/main/java/com/mindata/blockchain/block/check/CheckerManager.java b/src/main/java/com/mindata/blockchain/block/check/CheckerManager.java index 96ae55da0bc6930d1c319ccaa8e806fe9c2792d7..ac8ba6a3b8e590414fe71ef4198ab81371b25af5 100644 --- a/src/main/java/com/mindata/blockchain/block/check/CheckerManager.java +++ b/src/main/java/com/mindata/blockchain/block/check/CheckerManager.java @@ -21,6 +21,11 @@ public class CheckerManager { * @return 校验结果 */ public RpcCheckBlockBody check(Block block) { + int code= blockChecker.checkSign(block); + if (code != 0) { + return new RpcCheckBlockBody(-1, "block的签名不合法"); + } + int number = blockChecker.checkNum(block); if (number != 0) { return new RpcCheckBlockBody(-1, "block的number不合法"); diff --git a/src/main/java/com/mindata/blockchain/block/check/local/DbBlockChecker.java b/src/main/java/com/mindata/blockchain/block/check/local/DbBlockChecker.java index 84f8d0e5e71e7610de034f1ed5d41f782b5083ed..56aad6527683e9085c025e0bf837bd45fe716dff 100644 --- a/src/main/java/com/mindata/blockchain/block/check/local/DbBlockChecker.java +++ b/src/main/java/com/mindata/blockchain/block/check/local/DbBlockChecker.java @@ -3,8 +3,13 @@ package com.mindata.blockchain.block.check.local; import cn.hutool.core.util.StrUtil; import com.mindata.blockchain.block.Block; import com.mindata.blockchain.block.check.BlockChecker; +import com.mindata.blockchain.common.Sha256; +import com.mindata.blockchain.common.exception.TrustSDKException; import com.mindata.blockchain.core.manager.DbBlockManager; import com.mindata.blockchain.core.manager.PermissionManager; +import com.mindata.blockchain.core.requestbody.BlockRequestBody; +import com.mindata.blockchain.core.service.BlockService; + import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -19,6 +24,9 @@ public class DbBlockChecker implements BlockChecker { private DbBlockManager dbBlockManager; @Resource private PermissionManager permissionManager; + + @Resource + private BlockService blockService; @Override public int checkNum(Block block) { @@ -66,8 +74,60 @@ public class DbBlockChecker implements BlockChecker { } return 0; } + + @Override + public int checkSign(Block block) { + if(!checkBlockHashSign(block)) { + return -1; + } + return 0; + } private Block getLastBlock() { return dbBlockManager.getLastBlock(); } + + public String checkBlock(Block block) { + if(!checkBlockHashSign(block)) return block.getHash(); + + String preHash = block.getBlockHeader().getHashPreviousBlock(); + if(preHash == null) return null; + + Block preBlock = dbBlockManager.getBlockByHash(preHash); + if(preBlock == null) return block.getHash(); + + int localNum = preBlock.getBlockHeader().getNumber(); + //当前区块+1等于下一个区块时才同意 + if (localNum + 1 != block.getBlockHeader().getNumber()) { + return block.getHash(); + } + if(block.getBlockHeader().getTimeStamp() <= preBlock.getBlockHeader().getTimeStamp()) { + return block.getHash(); + } + + + return null; + } + + /** + * 检测区块签名及hash是否符合 + * @param block + * @return + */ + private boolean checkBlockHashSign(Block block) { + BlockRequestBody blockRequestBody = new BlockRequestBody(); + blockRequestBody.setBlockBody(block.getBlockBody()); + blockRequestBody.setPublicKey(block.getBlockHeader().getPublicKey()); + try { + if(blockService.check(blockRequestBody) != null) return false; + } catch (TrustSDKException e) { + return false; + } + + String hash = Sha256.sha256(block.getBlockHeader().toString() + block.getBlockBody().toString()); + if(!StrUtil.equals(block.getHash(),hash)) return false; + + return true; + } + } diff --git a/src/main/java/com/mindata/blockchain/core/controller/BlockController.java b/src/main/java/com/mindata/blockchain/core/controller/BlockController.java index 35a6fbc825c1cbff294a28d8756825b37434212b..0b759eabdfa7a31a4c844b064c1a5b8f8055e08d 100644 --- a/src/main/java/com/mindata/blockchain/core/controller/BlockController.java +++ b/src/main/java/com/mindata/blockchain/core/controller/BlockController.java @@ -1,10 +1,20 @@ package com.mindata.blockchain.core.controller; -import cn.hutool.core.collection.CollectionUtil; +import javax.annotation.Resource; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + import com.mindata.blockchain.ApplicationContextProvider; import com.mindata.blockchain.block.Block; import com.mindata.blockchain.block.Instruction; import com.mindata.blockchain.block.Operation; +import com.mindata.blockchain.block.check.BlockChecker; import com.mindata.blockchain.common.exception.TrustSDKException; import com.mindata.blockchain.core.bean.BaseData; import com.mindata.blockchain.core.bean.ResultGenerator; @@ -21,11 +31,8 @@ import com.mindata.blockchain.socket.client.PacketSender; import com.mindata.blockchain.socket.packet.BlockPacket; import com.mindata.blockchain.socket.packet.PacketBuilder; import com.mindata.blockchain.socket.packet.PacketType; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PageableDefault; -import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; +import cn.hutool.core.collection.CollectionUtil; /** * @author wuweifeng wrote on 2018/3/7. @@ -45,6 +52,8 @@ public class BlockController { private SyncManager syncManager; @Resource private MessageManager messageManager; + @Resource + private BlockChecker blockChecker; /** * 添加一个block,需要先在InstructionController构建1-N个instruction指令,然后调用该接口生成Block @@ -55,8 +64,9 @@ public class BlockController { */ @PostMapping public BaseData add(@RequestBody BlockRequestBody blockRequestBody) throws TrustSDKException { - if (blockService.check(blockRequestBody) != null) { - return ResultGenerator.genFailResult(blockService.check(blockRequestBody)); + String msg = blockService.check(blockRequestBody); + if (msg != null) { + return ResultGenerator.genFailResult(msg); } return ResultGenerator.genSuccessResult(blockService.addBlock(blockRequestBody)); } @@ -122,6 +132,25 @@ public class BlockController { ApplicationContextProvider.publishEvent(new DbSyncEvent("")); return ResultGenerator.genSuccessResult(syncManager.findAll(pageable)); } + + /** + * 全量检测区块是否正常 + * @return + * null - 通过 + * hash - 第一个异常hash + */ + @GetMapping("checkb") + public BaseData checkAllBlock() { + + Block block = dbBlockManager.getFirstBlock(); + + String hash = null; + while(block != null && hash == null) { + hash = blockChecker.checkBlock(block); + block = dbBlockManager.getNextBlock(block); + } + return ResultGenerator.genSuccessResult(hash); + } @GetMapping("/next") public BaseData nextBlock() { diff --git a/src/main/java/com/mindata/blockchain/core/service/InstructionService.java b/src/main/java/com/mindata/blockchain/core/service/InstructionService.java index b7d1bb72a53c2da1c69e80119b693b0bb3d3297c..ee9c72eefbe3945a5d369f6b125976ded9d6160b 100644 --- a/src/main/java/com/mindata/blockchain/core/service/InstructionService.java +++ b/src/main/java/com/mindata/blockchain/core/service/InstructionService.java @@ -60,8 +60,7 @@ public class InstructionService { instruction.setInstructionId(CommonUtil.generateUuid()); } instruction.setTimeStamp(CommonUtil.getNow()); - String buildStr = instructionBody.getOperation() + instructionBody.getTable() + instructionBody - .getInstructionId() + instructionBody.getJson() + instructionBody.getOldJson(); + String buildStr = getSignString(instruction); //设置签名,供其他人验证 instruction.setSign(TrustSDK.signString(instructionBody.getPrivateKey(), buildStr)); //设置hash,防止篡改 @@ -69,6 +68,12 @@ public class InstructionService { return instruction; } + + private String getSignString(Instruction instruction) { + return instruction.getOperation() + instruction.getTable() + instruction + .getInstructionId() + (instruction.getJson()==null?"":instruction.getJson()) + + (instruction.getOldJson()==null?"":instruction.getOldJson()); + } /** * 根据一个指令,计算它的回滚时的指令。
@@ -95,14 +100,12 @@ public class InstructionService {
}
public boolean checkSign(Instruction instruction) throws TrustSDKException {
- String buildStr = instruction.getOperation() +
- instruction.getTable() + instruction.getJson();
+ String buildStr = getSignString(instruction);
return TrustSDK.verifyString(instruction.getPublicKey(), buildStr, instruction.getSign());
}
public boolean checkHash(Instruction instruction) {
- String buildStr = instruction.getOperation() +
- instruction.getTable() + instruction.getJson();
+ String buildStr = getSignString(instruction);
return Sha256.sha256(buildStr).equals(instruction.getHash());
}
}
diff --git a/src/main/java/com/mindata/blockchain/socket/handler/client/FetchBlockResponseHandler.java b/src/main/java/com/mindata/blockchain/socket/handler/client/FetchBlockResponseHandler.java
index 61e10883559996eabfc9883d8ceab2c865c2f9e4..423ab5bca058c09ad2b37ff0d01db3310e9b51cc 100644
--- a/src/main/java/com/mindata/blockchain/socket/handler/client/FetchBlockResponseHandler.java
+++ b/src/main/java/com/mindata/blockchain/socket/handler/client/FetchBlockResponseHandler.java
@@ -10,6 +10,8 @@ import com.mindata.blockchain.socket.body.RpcCheckBlockBody;
import com.mindata.blockchain.socket.client.PacketSender;
import com.mindata.blockchain.socket.packet.BlockPacket;
import com.mindata.blockchain.socket.packet.NextBlockPacketBuilder;
+import com.mindata.blockchain.socket.pbft.queue.NextBlockQueue;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.ChannelContext;
@@ -38,6 +40,8 @@ public class FetchBlockResponseHandler extends AbstractBlockHandler