Program: 35129
Project: 35129
Buggy source:
/** 
 * 1. change spending output status  (cache and database) 2. save new input 3. save new unSpend output (cache and database) 4. finally, calc balance
 */
@Override @DbSession public void save(CoinData coinData,Transaction tx) throws NulsException {
  UtxoData utxoData=(UtxoData)coinData;
  List<UtxoInputPo> inputPoList=new ArrayList<>();
  List<UtxoOutput> spends=new ArrayList<>();
  List<UtxoOutputPo> spendPoList=new ArrayList<>();
  List<TxAccountRelationPo> txRelations=new ArrayList<>();
  Set<String> addressSet=new HashSet<>();
  lock.lock();
  try {
    processDataInput(utxoData,inputPoList,spends,spendPoList,addressSet);
    List<UtxoOutputPo> outputPoList=new ArrayList<>();
    for (int i=0; i < utxoData.getOutputs().size(); i++) {
      UtxoOutput output=utxoData.getOutputs().get(i);
      output=ledgerCacheService.getUtxo(output.getKey());
      if (output == null) {
        throw new NulsRuntimeException(ErrorCode.DATA_NOT_FOUND);
      }
      if (output.isConfirm() || OutPutStatusEnum.UTXO_SPENT == output.getStatus()) {
        Log.error("String_Node_Str" + output.getStatus().name());
        throw new NulsRuntimeException(ErrorCode.DATA_ERROR,"String_Node_Str");
      }
      if (OutPutStatusEnum.UTXO_UNCONFIRM_CONSENSUS_LOCK == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRM_CONSENSUS_LOCK);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRM_TIME_LOCK == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRM_TIME_LOCK);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRM_UNSPEND == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRM_UNSPEND);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRM_SPEND == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRM_SPEND);
      }
      UtxoOutputPo outputPo=UtxoTransferTool.toOutputPojo(output);
      outputPoList.add(outputPo);
      addressSet.add(Address.fromHashs(output.getAddress()).getBase58());
    }
    for (    String address : addressSet) {
      TxAccountRelationPo relationPo=new TxAccountRelationPo(tx.getHash().getDigestHex(),address);
      txRelations.add(relationPo);
    }
    outputDataService.updateStatus(spendPoList);
    inputDataService.save(inputPoList);
    outputDataService.save(outputPoList);
    relationDataService.save(txRelations);
    afterSaveDatabase(spends,utxoData,tx);
    for (    String address : addressSet) {
      UtxoTransactionTool.getInstance().calcBalance(address,true);
    }
  }
 catch (  Exception e) {
    throw e;
  }
 finally {
    lock.unlock();
  }
}

Fixed version (ground truth):
/** 
 * 1. change spending output status  (cache and database) 2. save new input 3. save new unSpend output (cache and database) 4. finally, calc balance
 */
@Override @DbSession public void save(CoinData coinData,Transaction tx) throws NulsException {
  UtxoData utxoData=(UtxoData)coinData;
  List<UtxoInputPo> inputPoList=new ArrayList<>();
  List<UtxoOutput> spends=new ArrayList<>();
  List<UtxoOutputPo> spendPoList=new ArrayList<>();
  List<TxAccountRelationPo> txRelations=new ArrayList<>();
  Set<String> addressSet=new HashSet<>();
  lock.lock();
  try {
    processDataInput(utxoData,inputPoList,spends,spendPoList,addressSet);
    List<UtxoOutputPo> outputPoList=new ArrayList<>();
    for (int i=0; i < utxoData.getOutputs().size(); i++) {
      UtxoOutput output=utxoData.getOutputs().get(i);
      output=ledgerCacheService.getUtxo(output.getKey());
      if (output == null) {
        throw new NulsRuntimeException(ErrorCode.DATA_NOT_FOUND);
      }
      if (output.isConfirm() || OutPutStatusEnum.UTXO_SPENT == output.getStatus()) {
        Log.error("String_Node_Str" + output.getStatus().name());
        throw new NulsRuntimeException(ErrorCode.DATA_ERROR,"String_Node_Str");
      }
      if (OutPutStatusEnum.UTXO_UNCONFIRMED_CONSENSUS_LOCK == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRMED_CONSENSUS_LOCK);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRMED_TIME_LOCK == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRMED_TIME_LOCK);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRMED_UNSPENT == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRMED_UNSPENT);
      }
 else       if (OutPutStatusEnum.UTXO_UNCONFIRMED_SPENT == output.getStatus()) {
        output.setStatus(OutPutStatusEnum.UTXO_CONFIRMED_SPENT);
      }
      UtxoOutputPo outputPo=UtxoTransferTool.toOutputPojo(output);
      outputPoList.add(outputPo);
      addressSet.add(Address.fromHashs(output.getAddress()).getBase58());
    }
    for (    String address : addressSet) {
      TxAccountRelationPo relationPo=new TxAccountRelationPo(tx.getHash().getDigestHex(),address);
      txRelations.add(relationPo);
    }
    outputDataService.updateStatus(spendPoList);
    inputDataService.save(inputPoList);
    outputDataService.save(outputPoList);
    relationDataService.save(txRelations);
    afterSaveDatabase(spends,utxoData,tx);
    for (    String address : addressSet) {
      UtxoTransactionTool.getInstance().calcBalance(address,true);
    }
  }
 catch (  Exception e) {
    throw e;
  }
 finally {
    lock.unlock();
  }
}