Program: 35073
Project: 35073
Buggy source:
/** 
 * 此txList是待打包的块中的交易，所以toList是下一步的UTXO，应该校验它 coinData的交易和txList同处一个块中，txList中的to可能是coinData的from， 也就是可能存在，在同一个块中，下一笔输入就是上一笔的输出，所以需要校验它
 * @param transaction
 * @param txList
 * @return
 */
@Override public ValidateResult verifyCoinData(Transaction transaction,List<Transaction> txList){
  if (transaction == null || transaction.getCoinData() == null || txList == null) {
    return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.NULL_PARAMETER);
  }
  try {
    CoinData coinData=transaction.getCoinData();
    int initialCapacity=0;
    CoinData validateCoinData;
    List<Coin> validateToList;
    for (    Transaction tx : txList) {
      validateCoinData=tx.getCoinData();
      if (validateCoinData == null) {
        continue;
      }
      initialCapacity+=validateCoinData.getTo().size();
    }
    Map<String,Coin> validateUtxoMap=new HashMap<>(initialCapacity);
    Transaction tx;
    byte[] txHashBytes;
    Coin toOfValidate;
    for (int i=0, length=txList.size(); i < length; i++) {
      tx=txList.get(i);
      validateCoinData=tx.getCoinData();
      if (validateCoinData == null) {
        continue;
      }
      txHashBytes=tx.getHash().serialize();
      validateToList=validateCoinData.getTo();
      for (int k=0, toLength=validateToList.size(); k < toLength; k++) {
        toOfValidate=validateToList.get(k);
        validateUtxoMap.put(asString(Arrays.concatenate(txHashBytes,new VarInt(k).encode())),toOfValidate);
      }
    }
    List<Coin> froms=coinData.getFrom();
    int fromSize=froms.size();
    P2PKHScriptSig p2PKHScriptSig=null;
    byte[] user=null;
    if (fromSize > 0) {
      try {
        p2PKHScriptSig=P2PKHScriptSig.createFromBytes(transaction.getScriptSig());
        user=p2PKHScriptSig.getSignerHash160();
      }
 catch (      NulsException e) {
        return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.DATA_ERROR);
      }
    }
    HashSet set=new HashSet(fromSize);
    Na fromTotal=Na.ZERO;
    byte[] fromBytes;
    Coin fromInDBorList=null;
    byte[] fromAdressBytes=null;
    for (    Coin from : froms) {
      fromBytes=from.getOwner();
      fromInDBorList=utxoLedgerUtxoStorageService.getUtxo(fromBytes);
      if (fromInDBorList == null) {
        fromInDBorList=validateUtxoMap.get(fromBytes);
      }
      if (null == fromInDBorList) {
        if (null != utxoLedgerTransactionStorageService.getTxBytes(LedgerUtil.getTxHashBytes(fromBytes))) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.LEDGER_DOUBLE_SPENT,"String_Node_Str");
        }
 else {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.ORPHAN_TX);
        }
      }
 else {
        fromAdressBytes=fromInDBorList.getOwner();
        if (!checkPublicKeyHash(fromAdressBytes,user)) {
          Log.warn("String_Node_Str");
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.INVALID_INPUT);
        }
      }
      if (!transaction.isUnlockTx()) {
        if (TimeService.currentTimeMillis() < from.getLockTime()) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.UTXO_UNUSABLE);
        }
      }
 else {
        if (from.getLockTime() != -1) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.UTXO_STATUS_CHANGE);
        }
      }
      if (!set.add(asString(fromBytes))) {
        return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.LEDGER_DOUBLE_SPENT,"String_Node_Str");
      }
      fromTotal=fromTotal.add(from.getNa());
    }
    List<Coin> tos=coinData.getTo();
    Na toTotal=Na.ZERO;
    for (    Coin to : tos) {
      toTotal=toTotal.add(to.getNa());
    }
    if (fromTotal.compareTo(toTotal) < 0) {
      return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.INVALID_AMOUNT);
    }
  }
 catch (  Exception e) {
    Log.error(e);
    return ValidateResult.getFailedResult(CLASS_NAME,e.getMessage());
  }
  return ValidateResult.getSuccessResult();
}

Fixed version (ground truth):
/** 
 * 此txList是待打包的块中的交易，所以toList是下一步的UTXO，应该校验它 coinData的交易和txList同处一个块中，txList中的to可能是coinData的from， 也就是可能存在，在同一个块中，下一笔输入就是上一笔的输出，所以需要校验它
 * @param transaction
 * @param txList
 * @return
 */
@Override public ValidateResult verifyCoinData(Transaction transaction,List<Transaction> txList){
  if (transaction == null || transaction.getCoinData() == null || txList == null) {
    return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.NULL_PARAMETER);
  }
  try {
    CoinData coinData=transaction.getCoinData();
    int initialCapacity=0;
    CoinData validateCoinData;
    List<Coin> validateToList;
    for (    Transaction tx : txList) {
      validateCoinData=tx.getCoinData();
      if (validateCoinData == null) {
        continue;
      }
      initialCapacity+=validateCoinData.getTo().size();
    }
    Map<String,Coin> validateUtxoMap=new HashMap<>(initialCapacity);
    Transaction tx;
    byte[] txHashBytes;
    Coin toOfValidate;
    for (int i=0, length=txList.size(); i < length; i++) {
      tx=txList.get(i);
      validateCoinData=tx.getCoinData();
      if (validateCoinData == null) {
        continue;
      }
      txHashBytes=tx.getHash().serialize();
      validateToList=validateCoinData.getTo();
      for (int k=0, toLength=validateToList.size(); k < toLength; k++) {
        toOfValidate=validateToList.get(k);
        validateUtxoMap.put(asString(Arrays.concatenate(txHashBytes,new VarInt(k).encode())),toOfValidate);
      }
    }
    List<Coin> froms=coinData.getFrom();
    int fromSize=froms.size();
    P2PKHScriptSig p2PKHScriptSig=null;
    byte[] user=null;
    if (fromSize > 0) {
      try {
        p2PKHScriptSig=P2PKHScriptSig.createFromBytes(transaction.getScriptSig());
        user=p2PKHScriptSig.getSignerHash160();
      }
 catch (      NulsException e) {
        return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.DATA_ERROR);
      }
    }
    HashSet set=new HashSet(fromSize);
    Na fromTotal=Na.ZERO;
    byte[] fromBytes;
    Coin fromInDBorList=null;
    byte[] fromAdressBytes=null;
    for (    Coin from : froms) {
      fromBytes=from.getOwner();
      fromInDBorList=utxoLedgerUtxoStorageService.getUtxo(fromBytes);
      if (fromInDBorList == null) {
        fromInDBorList=validateUtxoMap.get(asString(fromBytes));
      }
      if (null == fromInDBorList) {
        if (null != utxoLedgerTransactionStorageService.getTxBytes(LedgerUtil.getTxHashBytes(fromBytes))) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.LEDGER_DOUBLE_SPENT,"String_Node_Str");
        }
 else {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.ORPHAN_TX);
        }
      }
 else {
        fromAdressBytes=fromInDBorList.getOwner();
        if (!checkPublicKeyHash(fromAdressBytes,user)) {
          Log.warn("String_Node_Str");
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.INVALID_INPUT);
        }
      }
      if (!transaction.isUnlockTx()) {
        if (TimeService.currentTimeMillis() < from.getLockTime()) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.UTXO_UNUSABLE);
        }
      }
 else {
        if (from.getLockTime() != -1) {
          return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.UTXO_STATUS_CHANGE);
        }
      }
      if (!set.add(asString(fromBytes))) {
        return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.LEDGER_DOUBLE_SPENT,"String_Node_Str");
      }
      fromTotal=fromTotal.add(from.getNa());
    }
    List<Coin> tos=coinData.getTo();
    Na toTotal=Na.ZERO;
    for (    Coin to : tos) {
      toTotal=toTotal.add(to.getNa());
    }
    if (fromTotal.compareTo(toTotal) < 0) {
      return ValidateResult.getFailedResult(CLASS_NAME,LedgerErrorCode.INVALID_AMOUNT);
    }
  }
 catch (  Exception e) {
    Log.error(e);
    return ValidateResult.getFailedResult(CLASS_NAME,e.getMessage());
  }
  return ValidateResult.getSuccessResult();
}