Program: 35075
Project: 35075
Buggy source:
/** 
 * 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、转发区块
 * @param blockContainer
 * @return boolean
 * @throws IOException
 */
public boolean addBlock(BlockContainer blockContainer) throws IOException {
  boolean isDownload=blockContainer.getStatus() == BlockContainerStatus.DOWNLOADING;
  Block block=blockContainer.getBlock();
  if (TimeService.currentTimeMillis() + PocConsensusConstant.DISCARD_FUTURE_BLOCKS_TIME < block.getHeader().getTime()) {
    return false;
  }
  block.verifyWithException();
  ValidateResult<List<Transaction>> validateResult=ledgerService.verifyDoubleSpend(block);
  if (validateResult.isFailed() && validateResult.getErrorCode().equals(LedgerErrorCode.LEDGER_DOUBLE_SPENT)) {
    RedPunishTransaction redPunishTransaction=new RedPunishTransaction();
    RedPunishData redPunishData=new RedPunishData();
    redPunishData.setAddress(AddressTool.getAddress(block.getHeader().getScriptSig()));
    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);
    NulsContext.getServiceBean(ConsensusService.class).newTx(redPunishTransaction);
    return false;
  }
  boolean verifyAndAddBlockResult=false;
  Lockers.CHAIN_LOCK.lock();
  try {
    verifyAndAddBlockResult=chainManager.getMasterChain().verifyAndAddBlock(block,isDownload);
  }
  finally {
    Lockers.CHAIN_LOCK.unlock();
  }
  if (verifyAndAddBlockResult) {
    boolean success=true;
    try {
      do {
        block.verifyWithException();
        List<Transaction> verifiedList=new ArrayList<>();
        for (        Transaction tx : block.getTxs()) {
          if (tx.getType() == ConsensusConstant.TX_TYPE_YELLOW_PUNISH || tx.getType() == ConsensusConstant.TX_TYPE_RED_PUNISH) {
            continue;
          }
          ValidateResult result=ledgerService.verifyCoinData(tx.getCoinData(),verifiedList);
          if (result.isSuccess()) {
            result=tx.verify();
            if (result.isFailed()) {
              Log.info("String_Node_Str" + result.getMessage());
              success=false;
              break;
            }
 else {
              verifiedList.add(tx);
            }
          }
 else {
            success=false;
            Log.info("String_Node_Str" + result.getMessage());
            break;
          }
        }
        if (!success) {
          break;
        }
        ValidateResult validateResult1=tansactionService.conflictDetect(block.getTxs());
        if (validateResult1.isFailed()) {
          success=false;
          Log.info("String_Node_Str" + validateResult1.getMessage());
          break;
        }
        Result result=blockService.saveBlock(block);
        success=result.isSuccess();
        if (!success) {
          Log.warn("String_Node_Str" + result.getMessage() + "String_Node_Str"+ block.getHeader().getHeight()+ "String_Node_Str"+ block.getHeader().getHash());
        }
      }
 while (false);
    }
 catch (    Exception e) {
      Log.error("String_Node_Str" + e.getMessage(),e);
    }
    if (success) {
      try {
        Block tempBlock=blockService.getBlock(block.getHeader().getHash()).getData();
        if (tempBlock.getHeader().getTxCount() != tempBlock.getTxs().size()) {
          Log.error("String_Node_Str" + block.getHeader().getHash());
        }
      }
 catch (      Exception e) {
        e.printStackTrace();
      }
      NulsContext.getInstance().setBestBlock(block);
      removeTxFromMemoryPool(block);
      forwardingBlock(blockContainer);
      return true;
    }
 else {
      Lockers.CHAIN_LOCK.lock();
      try {
        chainManager.getMasterChain().rollback(block);
      }
  finally {
        Lockers.CHAIN_LOCK.unlock();
      }
      NulsContext.getInstance().setBestBlock(chainManager.getBestBlock());
      Log.error("String_Node_Str" + block.getHeader().getHeight() + "String_Node_Str"+ isDownload);
    }
  }
 else {
    if (isDownload && !ConsensusStatusContext.isRunning()) {
      return false;
    }
    boolean hasFoundForkChain=checkAndAddForkChain(block);
    if (!hasFoundForkChain) {
      ChainLog.debug("String_Node_Str",block.getHeader().getHeight(),block.getHeader().getHash().getDigestHex());
      orphanBlockProvider.addBlock(blockContainer);
    }
  }
  return false;
}

Fixed version (ground truth):
/** 
 * 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、转发区块
 * @param blockContainer
 * @return boolean
 * @throws IOException
 */
public boolean addBlock(BlockContainer blockContainer) throws IOException {
  boolean isDownload=blockContainer.getStatus() == BlockContainerStatus.DOWNLOADING;
  Block block=blockContainer.getBlock();
  if (TimeService.currentTimeMillis() + PocConsensusConstant.DISCARD_FUTURE_BLOCKS_TIME < block.getHeader().getTime()) {
    return false;
  }
  block.verifyWithException();
  ValidateResult<List<Transaction>> validateResult=ledgerService.verifyDoubleSpend(block);
  if (validateResult.isFailed() && validateResult.getErrorCode().equals(LedgerErrorCode.LEDGER_DOUBLE_SPENT)) {
    RedPunishTransaction redPunishTransaction=new RedPunishTransaction();
    RedPunishData redPunishData=new RedPunishData();
    redPunishData.setAddress(AddressTool.getAddress(block.getHeader().getScriptSig()));
    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);
    NulsContext.getServiceBean(ConsensusService.class).newTx(redPunishTransaction);
    return false;
  }
  boolean verifyAndAddBlockResult=false;
  Lockers.CHAIN_LOCK.lock();
  try {
    verifyAndAddBlockResult=chainManager.getMasterChain().verifyAndAddBlock(block,isDownload);
  }
  finally {
    Lockers.CHAIN_LOCK.unlock();
  }
  if (verifyAndAddBlockResult) {
    boolean success=true;
    try {
      do {
        block.verifyWithException();
        List<Transaction> verifiedList=new ArrayList<>();
        for (        Transaction tx : block.getTxs()) {
          if (tx.getType() == ConsensusConstant.TX_TYPE_YELLOW_PUNISH || tx.getType() == ConsensusConstant.TX_TYPE_RED_PUNISH) {
            continue;
          }
          ValidateResult result=ledgerService.verifyCoinData(tx,verifiedList);
          if (result.isSuccess()) {
            result=tx.verify();
            if (result.isFailed()) {
              Log.info("String_Node_Str" + result.getMessage());
              success=false;
              break;
            }
 else {
              verifiedList.add(tx);
            }
          }
 else {
            success=false;
            Log.info("String_Node_Str" + result.getMessage());
            break;
          }
        }
        if (!success) {
          break;
        }
        ValidateResult validateResult1=tansactionService.conflictDetect(block.getTxs());
        if (validateResult1.isFailed()) {
          success=false;
          Log.info("String_Node_Str" + validateResult1.getMessage());
          break;
        }
        Result result=blockService.saveBlock(block);
        success=result.isSuccess();
        if (!success) {
          Log.warn("String_Node_Str" + result.getMessage() + "String_Node_Str"+ block.getHeader().getHeight()+ "String_Node_Str"+ block.getHeader().getHash());
        }
      }
 while (false);
    }
 catch (    Exception e) {
      Log.error("String_Node_Str" + e.getMessage(),e);
    }
    if (success) {
      try {
        Block tempBlock=blockService.getBlock(block.getHeader().getHash()).getData();
        if (tempBlock.getHeader().getTxCount() != tempBlock.getTxs().size()) {
          Log.error("String_Node_Str" + block.getHeader().getHash());
        }
      }
 catch (      Exception e) {
        e.printStackTrace();
      }
      NulsContext.getInstance().setBestBlock(block);
      removeTxFromMemoryPool(block);
      forwardingBlock(blockContainer);
      return true;
    }
 else {
      Lockers.CHAIN_LOCK.lock();
      try {
        chainManager.getMasterChain().rollback(block);
      }
  finally {
        Lockers.CHAIN_LOCK.unlock();
      }
      NulsContext.getInstance().setBestBlock(chainManager.getBestBlock());
      Log.error("String_Node_Str" + block.getHeader().getHeight() + "String_Node_Str"+ isDownload);
    }
  }
 else {
    if (isDownload && !ConsensusStatusContext.isRunning()) {
      return false;
    }
    boolean hasFoundForkChain=checkAndAddForkChain(block);
    if (!hasFoundForkChain) {
      ChainLog.debug("String_Node_Str",block.getHeader().getHeight(),block.getHeader().getHash().getDigestHex());
      orphanBlockProvider.addBlock(blockContainer);
    }
  }
  return false;
}