Search in sources :

Example 1 with ValidateResult

use of io.nuls.kernel.validate.ValidateResult in project nuls by nuls-io.

the class AccountLedgerResource method valiTransaction.

@POST
@Path("/transaction/valiTransaction")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "验证交易是否正确", notes = "result.data: resultJson 返回验证结果")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success") })
public RpcClientResult valiTransaction(@ApiParam(name = "form", value = "验证交易是否正确", required = true) BroadHexTxForm form) {
    if (StringUtils.isBlank(form.getTxHex())) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    try {
        byte[] data = Hex.decode(form.getTxHex());
        Transaction tx = TransactionManager.getInstance(new NulsByteBuffer(data));
        ValidateResult validateResult = tx.verify();
        if (validateResult.isFailed()) {
            return Result.getFailed(validateResult.getErrorCode()).toRpcClientResult();
        }
        validateResult = this.ledgerService.verifyCoinData(tx, new HashMap<>(), new HashSet<>());
        if (validateResult.isFailed() && !validateResult.getErrorCode().equals(TransactionErrorCode.ORPHAN_TX)) {
            return Result.getFailed(validateResult.getErrorCode()).toRpcClientResult();
        }
        Result result = Result.getSuccess();
        return result.toRpcClientResult();
    } catch (Exception e) {
        Log.error(e);
        return Result.getFailed(LedgerErrorCode.DATA_PARSE_ERROR).toRpcClientResult();
    }
}
Also used : TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) ValidateResult(io.nuls.kernel.validate.ValidateResult) CryptoException(io.nuls.core.tools.crypto.Exception.CryptoException) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 2 with ValidateResult

use of io.nuls.kernel.validate.ValidateResult in project nuls by nuls-io.

the class SmallBlockHandler method onMessage.

@Override
public void onMessage(SmallBlockMessage event, Node fromNode) {
    SmallBlock smallBlock = event.getMsgBody();
    if (null == smallBlock) {
        Log.warn("recieved a null smallBlock!");
        return;
    }
    BlockHeader header = smallBlock.getHeader();
    // 阻止恶意节点提前出块
    if (header.getTime() > (TimeService.currentTimeMillis() + ProtocolConstant.BLOCK_TIME_INTERVAL_SECOND * 1000)) {
        // Log.info("---------------" + TimeService.currentTimeMillis());
        return;
    }
    if (!SmallBlockDuplicateRemoval.needProcess(header.getHash())) {
        // Log.warn("block header 重复");
        return;
    }
    BlockHeader theBlockHeader = blockService.getBlockHeader(header.getHash()).getData();
    if (null != theBlockHeader) {
        // Log.warn("这个区块已存在");
        return;
    }
    ValidateResult result = header.verify();
    boolean isOrphan = result.getErrorCode() == TransactionErrorCode.ORPHAN_TX || result.getErrorCode() == TransactionErrorCode.ORPHAN_BLOCK;
    BlockLog.debug("recieve new block from(" + fromNode.getId() + "), tx count : " + header.getTxCount() + " , tx pool count : " + consensusService.getMemoryTxs().size() + " , header height:" + header.getHeight() + ", preHash:" + header.getPreHash() + " , hash:" + header.getHash() + ", addressHex:" + AddressTool.getStringAddressByBytes(header.getPackingAddress()) + "\n and verify block result: " + result.isSuccess() + " , verify message : " + result.getMsg() + " , isOrphan : " + isOrphan);
    if (result.isFailed() && !isOrphan) {
        BlockLog.debug("discard a SmallBlock:" + smallBlock.getHeader().getHash() + ", from:" + fromNode.getId() + " ,reason:" + result.getMsg());
        return;
    }
    Map<NulsDigestData, Transaction> txMap = new HashMap<>();
    for (Transaction tx : smallBlock.getSubTxList()) {
        txMap.put(tx.getHash(), tx);
    }
    List<NulsDigestData> needHashList = new ArrayList<>();
    for (NulsDigestData hash : smallBlock.getTxHashList()) {
        Transaction tx = txMap.get(hash);
        if (null == tx) {
            tx = transactionService.getTx(hash);
            if (tx != null) {
                smallBlock.getSubTxList().add(tx);
                txMap.put(hash, tx);
            }
        }
        if (null == tx) {
            needHashList.add(hash);
        }
    }
    if (!needHashList.isEmpty()) {
        // Log.info("block height : " + header.getHeight() + ", tx count : " + header.getTxCount() + " , get group tx of " + needHashList.size());
        GetTxGroupRequest request = new GetTxGroupRequest();
        GetTxGroupParam param = new GetTxGroupParam();
        param.setTxHashList(needHashList);
        request.setMsgBody(param);
        Result sendResult = this.messageBusService.sendToNode(request, fromNode, true);
        if (sendResult.isFailed()) {
            Log.warn("get tx group failed,height:" + header.getHeight());
        } else {
            NulsDigestData requestHash = null;
            try {
                requestHash = NulsDigestData.calcDigestData(request.getMsgBody().serialize());
            } catch (IOException e) {
                Log.error(e);
                return;
            }
            temporaryCacheManager.cacheSmallBlockWithRequest(requestHash, smallBlock);
        }
        return;
    }
    Block block = AssemblyBlockUtil.assemblyBlock(header, txMap, smallBlock.getTxHashList());
    consensusService.newBlock(block, fromNode);
}
Also used : SmallBlock(io.nuls.protocol.model.SmallBlock) HashMap(java.util.HashMap) GetTxGroupRequest(io.nuls.protocol.message.GetTxGroupRequest) ValidateResult(io.nuls.kernel.validate.ValidateResult) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ValidateResult(io.nuls.kernel.validate.ValidateResult) GetTxGroupParam(io.nuls.protocol.model.GetTxGroupParam) SmallBlock(io.nuls.protocol.model.SmallBlock)

Example 3 with ValidateResult

use of io.nuls.kernel.validate.ValidateResult in project nuls by nuls-io.

the class ForkChainProcess method doChange.

private boolean doChange(List<Block> successList, ChainContainer originalForkChain, List<Object[]> verifyResultList) {
    boolean changeSuccess = true;
    // add new block
    List<Block> addBlockList = originalForkChain.getChain().getAllBlockList();
    Result<Block> preBlockResult = blockService.getBlock(addBlockList.get(0).getHeader().getPreHash());
    Block preBlock = preBlockResult.getData();
    Block newBlock;
    // for (Block newBlock : addBlockList) {
    for (int i = 0, size = addBlockList.size(); i < size; i++) {
        newBlock = addBlockList.get(i);
        newBlock.verifyWithException();
        Map<String, Coin> toMaps = new HashMap<>();
        Set<String> fromSet = new HashSet<>();
        /**
         * pierre add 智能合约相关
         */
        long bestHeight = preBlock.getHeader().getHeight();
        byte[] stateRoot = ConsensusTool.getStateRoot(preBlock.getHeader());
        preBlock = newBlock;
        BlockHeader verifyHeader = newBlock.getHeader();
        byte[] receiveStateRoot = ConsensusTool.getStateRoot(verifyHeader);
        ContractResult contractResult;
        Map<String, Coin> contractUsedCoinMap = new HashMap<>();
        int totalGasUsed = 0;
        // 为本次验证区块增加一个合约的临时余额区,用于记录本次合约地址余额的变化
        contractService.createContractTempBalance();
        // 为本次验证区块创建一个批量执行合约的执行器
        contractService.createBatchExecute(stateRoot);
        // 为本次验证区块存储当前块的部分区块头信息(高度、时间、打包者地址)
        BlockHeader tempHeader = new BlockHeader();
        tempHeader.setTime(verifyHeader.getTime());
        tempHeader.setHeight(verifyHeader.getHeight());
        tempHeader.setPackingAddress(verifyHeader.getPackingAddress());
        contractService.createCurrentBlockHeader(tempHeader);
        List<ContractResult> contractResultList = new ArrayList<>();
        // 用于存储合约执行结果的stateRoot, 如果不为空,则说明验证、打包的区块是同一个节点
        byte[] tempStateRoot = null;
        for (Transaction tx : newBlock.getTxs()) {
            if (tx.isSystemTx()) {
                continue;
            }
            // 区块中可以消耗的最大Gas总量,超过这个值,如果还有消耗GAS的合约交易,则本区块中不再继续验证区块
            if (totalGasUsed > ContractConstant.MAX_PACKAGE_GAS) {
                if (ContractUtil.isGasCostContractTransaction(tx)) {
                    Log.info("verify block failed: Excess contract transaction detected.");
                    changeSuccess = false;
                    break;
                }
            }
            ValidateResult result = tx.verify();
            if (result.isSuccess()) {
                result = ledgerService.verifyCoinData(tx, toMaps, fromSet, bestHeight);
                if (result.isFailed()) {
                    ErrorData errorData = (ErrorData) result.getData();
                    if (null == errorData) {
                        Log.info("failed message:" + result.getMsg());
                    } else {
                        Log.info("failed message:" + errorData.getMsg());
                    }
                    changeSuccess = false;
                    break;
                }
            } else {
                ErrorData errorData = (ErrorData) result.getData();
                if (null == errorData) {
                    Log.info("failed message:" + result.getMsg());
                } else {
                    Log.info("failed message:" + errorData.getMsg());
                }
                changeSuccess = false;
                break;
            }
            // 验证时发现智能合约交易就调用智能合约
            if (ContractUtil.isContractTransaction(tx)) {
                contractResult = contractService.batchProcessTx(tx, bestHeight, newBlock, stateRoot, toMaps, contractUsedCoinMap, true).getData();
                if (contractResult != null) {
                    tempStateRoot = contractResult.getStateRoot();
                    totalGasUsed += contractResult.getGasUsed();
                    contractResultList.add(contractResult);
                }
            }
        }
        if (!changeSuccess) {
            break;
        }
        // 验证结束后移除临时余额区
        contractService.removeContractTempBalance();
        stateRoot = contractService.commitBatchExecute().getData();
        // 验证结束后移除批量执行合约的执行器
        contractService.removeBatchExecute();
        // 验证结束后移除当前区块头信息
        contractService.removeCurrentBlockHeader();
        // 如果不为空,则说明验证、打包的区块是同一个节点
        if (tempStateRoot != null) {
            stateRoot = tempStateRoot;
        }
        newBlock.getHeader().setStateRoot(stateRoot);
        for (ContractResult result : contractResultList) {
            result.setStateRoot(stateRoot);
        }
        // 验证世界状态根
        if ((receiveStateRoot != null || stateRoot != null) && !Arrays.equals(receiveStateRoot, stateRoot)) {
            Log.info("contract stateRoot incorrect. receiveStateRoot is {}, stateRoot is {}.", receiveStateRoot != null ? Hex.encode(receiveStateRoot) : receiveStateRoot, stateRoot != null ? Hex.encode(stateRoot) : stateRoot);
            changeSuccess = false;
            break;
        }
        // 验证CoinBase交易
        Object[] objects = verifyResultList.get(i);
        MeetingRound currentRound = (MeetingRound) objects[0];
        MeetingMember member = (MeetingMember) objects[1];
        if (!chainManager.getMasterChain().verifyCoinBaseTx(newBlock, currentRound, member)) {
            changeSuccess = false;
            break;
        }
        if (!changeSuccess) {
            break;
        }
        ValidateResult validateResult1 = tansactionService.conflictDetect(newBlock.getTxs());
        if (validateResult1.isFailed()) {
            Log.info("failed message:" + validateResult1.getMsg());
            changeSuccess = false;
            break;
        }
        try {
            Result result = blockService.saveBlock(newBlock);
            boolean success = result.isSuccess();
            if (success) {
                // 更新版本协议内容
                successList.add(newBlock);
                nulsProtocolProcess.processProtocolUpGrade(newBlock.getHeader());
                BlockHeader preHeader = blockService.getBlockHeader(newBlock.getHeader().getPreHash()).getData();
                randomSeedService.processBlock(newBlock.getHeader(), preHeader);
            } else {
                ChainLog.debug("save block error : " + result.getMsg() + " , block height : " + newBlock.getHeader().getHeight() + " , hash: " + newBlock.getHeader().getHash());
                changeSuccess = false;
                break;
            }
        } catch (Exception e) {
            Log.info("change fork chain error at save block, ", e);
            changeSuccess = false;
            break;
        }
    }
    if (!changeSuccess) {
        contractService.removeContractTempBalance();
        contractService.removeBatchExecute();
        contractService.removeCurrentBlockHeader();
    }
    return changeSuccess;
}
Also used : MeetingMember(io.nuls.consensus.poc.model.MeetingMember) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) MeetingRound(io.nuls.consensus.poc.model.MeetingRound) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException)

Example 4 with ValidateResult

use of io.nuls.kernel.validate.ValidateResult in project nuls by nuls-io.

the class BlockProcess method addBlock.

/**
 * Dealing with new blocks, the new block has two cases, the block when downloading and the latest block received, there are two different authentication logic
 *      * The download block is added. The verification round is not the current round. You need to restore the block to generate the current round status.
 *      * The new block received during operation must be verified with the latest round status
 *      * New block processing flow:
 *      * 1. Preprocessing, basic verification, including verification of block header field information, block size verification, signature verification
 *      * 2, try to add blocks to the main chain, first verify the block of the round and packaged people, if the verification fails, then put into the isolated block pool, if the verification is successful, then add into the main chain, add the memory state into
 *      * 3, verify the transaction of the block is legitimate, whether there are double flowers or other illegal transactions, if there is, then put in the isolated block pool, if not, save the block
 *      * 4, save the block header information, save the block transaction information
 *      * 5. Forwarding block
 * <p>
 * 处理新的区块,新区块有两种情况,下载时的区块和接收到的最新区块,两种有不同的验证逻辑
 * 下载中区块的添加,验证的轮次不是当前的轮次,需要还原区块产生当时的轮次状态
 * 运行中接收到的新区块,必须以当前最新的轮次状态来验证
 * 新区块处理的流程:
 * 1、预处理,做基本的验证,包括区块头字段信息的验证,区块大小的验证,签名的验证
 * 2、尝试向主链添加区块,先验证区块的轮次和打包人,如果验证失败则放入孤立区块池,如果验证成功,则添加进主链里,内存状态添加进去
 * 3、验证区块的交易是否合法,是否有双花或者其它不合法的交易,如果有,则放入孤立区块池里,如果没有,则保存区块
 * 4、保存区块头信息,保存区块交易信息
 * 5、转发区块
 *
 * @return boolean
 */
public boolean addBlock(BlockContainer blockContainer) throws IOException {
    if (NulsContext.mastUpGrade == true) {
        return false;
    }
    boolean isDownload = blockContainer.getStatus() == BlockContainerStatus.DOWNLOADING;
    Block block = blockContainer.getBlock();
    // 丢弃掉未来时间的区块
    if (TimeService.currentTimeMillis() + PocConsensusConstant.DISCARD_FUTURE_BLOCKS_TIME < block.getHeader().getTime()) {
        return false;
    }
    // Verify the the block, the content to be verified includes: whether the block size exceeds the limit,
    // whether the attribute of the block header is legal, the Merkel tree root is correct, the signature is correct,
    // and whether the expanded round of information is valid
    // 验证区块,需要验证的内容有:区块大小是否超过限制、区块头属性是否合法、梅克尔树根是否正确、签名是否正确、扩展的轮次信息是否合法
    block.verifyWithException();
    bifurcationUtil.validate(block.getHeader());
    ValidateResult<List<Transaction>> validateResult = ledgerService.verifyDoubleSpend(block);
    if (validateResult.isFailed() && validateResult.getErrorCode().equals(TransactionErrorCode.TRANSACTION_REPEATED)) {
        RedPunishTransaction redPunishTransaction = new RedPunishTransaction();
        RedPunishData redPunishData = new RedPunishData();
        byte[] packingAddress = AddressTool.getAddress(block.getHeader().getBlockSignature().getPublicKey());
        List<Agent> agentList = PocConsensusContext.getChainManager().getMasterChain().getChain().getAgentList();
        Agent agent = null;
        for (Agent a : agentList) {
            if (a.getDelHeight() > 0) {
                continue;
            }
            if (Arrays.equals(a.getPackingAddress(), packingAddress)) {
                agent = a;
                break;
            }
        }
        if (null == agent) {
            return false;
        }
        redPunishData.setAddress(agent.getAgentAddress());
        SmallBlock smallBlock = new SmallBlock();
        smallBlock.setHeader(block.getHeader());
        smallBlock.setTxHashList(block.getTxHashList());
        for (Transaction tx : validateResult.getData()) {
            smallBlock.addBaseTx(tx);
        }
        redPunishData.setEvidence(smallBlock.serialize());
        redPunishData.setReasonCode(PunishReasonEnum.DOUBLE_SPEND.getCode());
        redPunishTransaction.setTxData(redPunishData);
        redPunishTransaction.setTime(smallBlock.getHeader().getTime());
        CoinData coinData = ConsensusTool.getStopAgentCoinData(agent, redPunishTransaction.getTime() + PocConsensusConstant.RED_PUNISH_LOCK_TIME);
        redPunishTransaction.setCoinData(coinData);
        redPunishTransaction.setHash(NulsDigestData.calcDigestData(redPunishTransaction.serializeForHash()));
        TxMemoryPool.getInstance().add(redPunishTransaction, false);
        return false;
    }
    // Verify that the block round information is correct, if correct, join the main chain
    // 验证区块轮次信息是否正确、如果正确,则加入主链
    Result verifyAndAddBlockResult = chainManager.getMasterChain().verifyAndAddBlock(block, isDownload, false);
    if (verifyAndAddBlockResult.isSuccess()) {
        boolean success = true;
        try {
            do {
                // Verify that the block transaction is valid, save the block if the verification passes, and discard the block if it fails
                // 验证区块交易是否合法,如果验证通过则保存区块,如果失败则丢弃该块
                long time = System.currentTimeMillis();
                List<Future<Boolean>> futures = new ArrayList<>();
                List<Transaction> txs = block.getTxs();
                // 首先验证区块里的所有交易是否都属于当前版本的交易,如果有不包含的交易类型,丢弃该区块
                Set<Integer> txTypeSet = NulsVersionManager.getMainProtocolContainer().getTxMap().keySet();
                for (Transaction tx : txs) {
                    if (!txTypeSet.contains(tx.getType())) {
                        Log.info("--------------------- block tx discard, current protocol version:" + NulsVersionManager.getMainProtocolContainer().getVersion() + ",  tx.type:" + tx.getType());
                        return false;
                    }
                }
                for (Transaction tx : txs) {
                    Future<Boolean> res = signExecutor.submit(new Callable<Boolean>() {

                        @Override
                        public Boolean call() throws Exception {
                            ValidateResult verify = tx.verify();
                            /**
                             ***********************************************************
                             */
                            if (verify.isFailed()) {
                                Log.error(JSONUtils.obj2json(verify.getErrorCode()));
                            }
                            /**
                             ***********************************************************
                             */
                            boolean result = verify.isSuccess();
                            return result;
                        }
                    });
                    futures.add(res);
                }
                Map<String, Coin> toMaps = new HashMap<>();
                Set<String> fromSet = new HashSet<>();
                /**
                 * pierre add 智能合约相关
                 */
                BlockHeader bestBlockHeader = NulsContext.getInstance().getBestBlock().getHeader();
                BlockHeader verifyHeader = block.getHeader();
                long bestHeight = bestBlockHeader.getHeight();
                byte[] receiveStateRoot = ConsensusTool.getStateRoot(verifyHeader);
                byte[] stateRoot = ConsensusTool.getStateRoot(bestBlockHeader);
                ContractResult contractResult;
                Map<String, Coin> contractUsedCoinMap = new HashMap<>();
                int totalGasUsed = 0;
                // 为本次验证区块增加一个合约的临时余额区,用于记录本次合约地址余额的变化
                contractService.createContractTempBalance();
                // 为本次验证区块创建一个批量执行合约的执行器
                contractService.createBatchExecute(stateRoot);
                // 为本次验证区块存储当前块的部分区块头信息(高度、时间、打包者地址)
                BlockHeader tempHeader = new BlockHeader();
                tempHeader.setTime(verifyHeader.getTime());
                tempHeader.setHeight(verifyHeader.getHeight());
                tempHeader.setPackingAddress(verifyHeader.getPackingAddress());
                contractService.createCurrentBlockHeader(tempHeader);
                List<ContractResult> contractResultList = new ArrayList<>();
                // 用于存储合约执行结果的stateRoot, 如果不为空,则说明验证、打包的区块是同一个节点
                byte[] tempStateRoot = null;
                for (Transaction tx : txs) {
                    if (tx.isSystemTx()) {
                        continue;
                    }
                    // 区块中可以消耗的最大Gas总量,超过这个值,如果还有消耗GAS的合约交易,则本区块中不再继续验证区块
                    if (totalGasUsed > ContractConstant.MAX_PACKAGE_GAS) {
                        if (ContractUtil.isGasCostContractTransaction(tx)) {
                            Log.info("verify block failed: Excess contract transaction detected.");
                            success = false;
                            break;
                        }
                    }
                    ValidateResult result = ledgerService.verifyCoinData(tx, toMaps, fromSet);
                    if (result.isFailed()) {
                        Log.info("failed message:" + result.getMsg());
                        success = false;
                        break;
                    }
                    // 验证时发现智能合约交易就调用智能合约
                    if (ContractUtil.isContractTransaction(tx)) {
                        contractResult = contractService.batchProcessTx(tx, bestHeight, block, stateRoot, toMaps, contractUsedCoinMap, false).getData();
                        if (contractResult != null) {
                            tempStateRoot = contractResult.getStateRoot();
                            totalGasUsed += contractResult.getGasUsed();
                            contractResultList.add(contractResult);
                        }
                    }
                }
                if (!success) {
                    break;
                }
                // 验证结束后移除临时余额区
                contractService.removeContractTempBalance();
                stateRoot = contractService.commitBatchExecute().getData();
                // 验证结束后移除批量执行合约的执行器
                contractService.removeBatchExecute();
                // 验证结束后移除当前区块头信息
                contractService.removeCurrentBlockHeader();
                // 如果不为空,则说明验证、打包的区块是同一个节点
                if (tempStateRoot != null) {
                    stateRoot = tempStateRoot;
                }
                block.getHeader().setStateRoot(stateRoot);
                for (ContractResult result : contractResultList) {
                    result.setStateRoot(stateRoot);
                }
                // 验证世界状态根
                if ((receiveStateRoot != null || stateRoot != null) && !Arrays.equals(receiveStateRoot, stateRoot)) {
                    Log.info("contract stateRoot incorrect. receiveStateRoot is {}, stateRoot is {}.", receiveStateRoot != null ? Hex.encode(receiveStateRoot) : receiveStateRoot, stateRoot != null ? Hex.encode(stateRoot) : stateRoot);
                    success = false;
                    break;
                }
                // 验证CoinBase交易
                Object[] objects = (Object[]) verifyAndAddBlockResult.getData();
                MeetingRound currentRound = (MeetingRound) objects[0];
                MeetingMember member = (MeetingMember) objects[1];
                if (!chainManager.getMasterChain().verifyCoinBaseTx(block, currentRound, member)) {
                    success = false;
                    break;
                }
                if (!success) {
                    break;
                }
                ValidateResult validateResult1 = tansactionService.conflictDetect(block.getTxs());
                if (validateResult1.isFailed()) {
                    success = false;
                    Log.info("failed message:" + validateResult1.getMsg());
                    break;
                }
                for (Future<Boolean> future : futures) {
                    if (!future.get()) {
                        success = false;
                        Log.info("verify failed!");
                        break;
                    }
                }
                // Log.info("验证交易耗时:" + (System.currentTimeMillis() - time));
                if (!success) {
                    break;
                }
                time = System.currentTimeMillis();
                // save block
                Result result = blockService.saveBlock(block);
                success = result.isSuccess();
                if (!success) {
                    Log.warn("save block fail : reason : " + result.getMsg() + ", block height : " + block.getHeader().getHeight() + ", hash : " + block.getHeader().getHash());
                } else {
                    randomSeedService.processBlock(block.getHeader(), bestBlockHeader);
                    RewardStatisticsProcess.addBlock(block);
                    // 更新版本协议内容
                    nulsProtocolProcess.processProtocolUpGrade(block.getHeader());
                    BlockLog.debug("save block height : " + block.getHeader().getHeight() + " , hash : " + block.getHeader().getHash());
                }
            // Log.info("保存耗时:" + (System.currentTimeMillis() - time));
            } while (false);
        } catch (Exception e) {
            Log.error("save block error : " + e.getMessage(), e);
        }
        if (success) {
            long t = System.currentTimeMillis();
            NulsContext.getInstance().setBestBlock(block);
            // remove tx from memory pool
            removeTxFromMemoryPool(block);
            // Log.info("移除内存交易耗时:" + (System.currentTimeMillis() - t));
            // 转发区块
            forwardingBlock(blockContainer);
            return true;
        } else {
            contractService.removeContractTempBalance();
            contractService.removeBatchExecute();
            contractService.removeCurrentBlockHeader();
            chainManager.getMasterChain().rollback(block);
            NulsContext.getInstance().setBestBlock(chainManager.getBestBlock());
            Log.error("save block fail : " + block.getHeader().getHeight() + " , isDownload : " + isDownload);
        }
    } else {
        // 下载中验证失败的区块直接丢弃
        if (isDownload && !ConsensusStatusContext.isRunning()) {
            return false;
        }
        boolean hasFoundForkChain = checkAndAddForkChain(block);
        if (!hasFoundForkChain) {
            ChainLog.debug("add block {} - {} in queue", block.getHeader().getHeight(), block.getHeader().getHash().getDigestHex());
            orphanBlockProvider.addBlock(blockContainer);
        }
    }
    return false;
}
Also used : RedPunishTransaction(io.nuls.consensus.poc.protocol.tx.RedPunishTransaction) MeetingMember(io.nuls.consensus.poc.model.MeetingMember) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) RedPunishData(io.nuls.consensus.poc.protocol.entity.RedPunishData) MeetingRound(io.nuls.consensus.poc.model.MeetingRound) SmallBlock(io.nuls.protocol.model.SmallBlock) Agent(io.nuls.consensus.poc.protocol.entity.Agent) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) IOException(java.io.IOException) RedPunishTransaction(io.nuls.consensus.poc.protocol.tx.RedPunishTransaction) SmallBlock(io.nuls.protocol.model.SmallBlock) Future(java.util.concurrent.Future)

Example 5 with ValidateResult

use of io.nuls.kernel.validate.ValidateResult in project nuls by nuls-io.

the class BifurcationUtil method validate.

public ValidateResult validate(BlockHeader header) {
    ValidateResult result = ValidateResult.getSuccessResult();
    if (NulsContext.MAIN_NET_VERSION <= 1) {
        return result;
    }
    if (ConsensusConfig.getSeedNodeStringList().indexOf(AddressTool.getStringAddressByBytes(header.getPackingAddress())) >= 0) {
        return result;
    }
    if (header.getHeight() == 0L) {
        return result;
    }
    if (header.getHeight() > NulsContext.getInstance().getBestHeight()) {
        return result;
    }
    BlockHeader otherBlockHeader = blockService.getBlockHeader(header.getHeight()).getData();
    if (null != otherBlockHeader && !otherBlockHeader.getHash().equals(header.getHash()) && Arrays.equals(otherBlockHeader.getPackingAddress(), header.getPackingAddress())) {
        Log.info("-+-+-+-+-+-+-+-+- Received block with the same height and different hashes as the latest local block -+-+-+-+-+-+-+-+- ");
        Log.info("-+-+-+-+-+-+-+-+- height:" + header.getHeight() + ", hash of received block:" + header.getHash().getDigestHex() + ", hash of local latest block:" + otherBlockHeader.getHash().getDigestHex());
        Log.info("-+-+-+-+-+-+-+-+- Packing address of received block:" + AddressTool.getStringAddressByBytes(header.getPackingAddress()) + ", Packing address of local latest block:" + AddressTool.getStringAddressByBytes(otherBlockHeader.getPackingAddress()));
        List<Agent> agentList = PocConsensusContext.getChainManager().getMasterChain().getChain().getAgentList();
        Agent agent = null;
        for (Agent a : agentList) {
            if (a.getDelHeight() > 0) {
                continue;
            }
            if (Arrays.equals(a.getPackingAddress(), header.getPackingAddress())) {
                agent = a;
                break;
            }
        }
        if (null == agent) {
            return result;
        }
        recordEvidence(agent, header, otherBlockHeader);
        if (!isRedPunish(agent)) {
            return result;
        }
        RedPunishTransaction redPunishTransaction = new RedPunishTransaction();
        RedPunishData redPunishData = new RedPunishData();
        redPunishData.setAddress(agent.getAgentAddress());
        long txTime = 0;
        try {
            // 连续3轮 每一轮两个区块头作为证据 一共 3 * 2 个区块头作为证据
            byte[][] headers = new byte[NulsContext.REDPUNISH_BIFURCATION * 2][];
            List<Evidence> list = bifurcationEvidenceMap.get(AddressTool.getStringAddressByBytes(agent.getPackingAddress()));
            for (int i = 0; i < list.size() && i < NulsContext.REDPUNISH_BIFURCATION; i++) {
                Evidence evidence = list.get(i);
                int s = i * 2;
                headers[s] = evidence.getBlockHeader1().serialize();
                headers[++s] = evidence.getBlockHeader2().serialize();
                txTime = (evidence.getBlockHeader1().getTime() + evidence.getBlockHeader2().getTime()) / 2;
            }
            redPunishData.setEvidence(ArraysTool.concatenate(headers));
        } catch (Exception e) {
            Log.error(e);
            return result;
        }
        redPunishData.setReasonCode(PunishReasonEnum.BIFURCATION.getCode());
        redPunishTransaction.setTxData(redPunishData);
        redPunishTransaction.setTime(txTime);
        CoinData coinData = null;
        try {
            coinData = ConsensusTool.getStopAgentCoinData(agent, redPunishTransaction.getTime() + PocConsensusConstant.RED_PUNISH_LOCK_TIME);
        } catch (IOException e) {
            Log.error(e);
            return result;
        }
        redPunishTransaction.setCoinData(coinData);
        try {
            redPunishTransaction.setHash(NulsDigestData.calcDigestData(redPunishTransaction.serializeForHash()));
        } catch (IOException e) {
            Log.error(e);
            return result;
        }
        TxMemoryPool.getInstance().add(redPunishTransaction, false);
        return result;
    }
    return result;
}
Also used : Agent(io.nuls.consensus.poc.protocol.entity.Agent) RedPunishTransaction(io.nuls.consensus.poc.protocol.tx.RedPunishTransaction) CoinData(io.nuls.kernel.model.CoinData) ValidateResult(io.nuls.kernel.validate.ValidateResult) IOException(java.io.IOException) IOException(java.io.IOException) RedPunishData(io.nuls.consensus.poc.protocol.entity.RedPunishData) Evidence(io.nuls.consensus.poc.model.Evidence) BlockHeader(io.nuls.kernel.model.BlockHeader)

Aggregations

ValidateResult (io.nuls.kernel.validate.ValidateResult)31 NulsException (io.nuls.kernel.exception.NulsException)12 IOException (java.io.IOException)8 Agent (io.nuls.consensus.poc.protocol.entity.Agent)6 RedPunishTransaction (io.nuls.consensus.poc.protocol.tx.RedPunishTransaction)6 Coin (io.nuls.kernel.model.Coin)6 Transaction (io.nuls.kernel.model.Transaction)6 RedPunishData (io.nuls.consensus.poc.protocol.entity.RedPunishData)5 AgentPo (io.nuls.consensus.poc.storage.po.AgentPo)5 TransactionSignature (io.nuls.kernel.script.TransactionSignature)5 HashSet (java.util.HashSet)5 CreateAgentTransaction (io.nuls.consensus.poc.protocol.tx.CreateAgentTransaction)4 CoinData (io.nuls.kernel.model.CoinData)4 SmallBlock (io.nuls.protocol.model.SmallBlock)4 ArrayList (java.util.ArrayList)4 BaseTest (io.nuls.consensus.poc.BaseTest)3 DepositPo (io.nuls.consensus.poc.storage.po.DepositPo)3 ContractResult (io.nuls.contract.dto.ContractResult)3 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)3 CoinBaseTransaction (io.nuls.protocol.model.tx.CoinBaseTransaction)3