public Value getBalance(boolean includeReceiving) { lock.lock(); try { long value = 0; for (OutPointOutput utxo : getUnspentOutputs(includeReceiving).values()) { value = LongMath.checkedAdd(value, utxo.getValueLong()); } return type.value(value); } finally { lock.unlock(); } }
@Override public int compare(OutPointOutput a, OutPointOutput b) { int depth1 = a.getDepthInBlocks(); int depth2 = b.getDepthInBlocks(); long aValue = a.getValueLong(); long bValue = b.getValueLong(); BigInteger aCoinDepth = BigInteger.valueOf(aValue).multiply(BigInteger.valueOf(depth1)); BigInteger bCoinDepth = BigInteger.valueOf(bValue).multiply(BigInteger.valueOf(depth2)); int c1 = bCoinDepth.compareTo(aCoinDepth); if (c1 != 0) return c1; // The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size. if (aValue != bValue) return aValue > bValue ? 1 : -1; // They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering. BigInteger aHash = a.getTxHash().toBigInteger(); BigInteger bHash = b.getTxHash().toBigInteger(); return aHash.compareTo(bHash); } });
public CoinSelection select(Coin biTarget, List<OutPointOutput> candidates) { long target = biTarget.value; HashSet<OutPointOutput> selected = new HashSet<>(); // Sort the inputs by age*value so we get the highest "coindays" spent. // TODO: Consider changing the wallets internal format to track just outputs and keep them ordered. ArrayList<OutPointOutput> sortedOutputs = new ArrayList<>(candidates); // When calculating the wallet balance, we may be asked to select all possible coins, if so, avoid sorting // them in order to improve performance. if (!biTarget.equals(NetworkParameters.MAX_MONEY)) { sortOutputs(sortedOutputs); } // Now iterate over the sorted outputs until we have got as close to the target as possible or a little // bit over (excessive value will be change). long total = 0; for (OutPointOutput output : sortedOutputs) { if (total >= target) break; // Only pick chain-included transactions, or transactions that are ours and pending. if (!shouldSelect(output)) continue; selected.add(output); total += output.getValueLong(); } // Total may be lower than target here, if the given candidates were insufficient to create to requested // transaction. return new CoinSelection(Coin.valueOf(total), selected); }
private static Protos.UnspentOutput makeUTXOProto(OutPointOutput utxo) { Protos.UnspentOutput.Builder utxoBuilder = Protos.UnspentOutput.newBuilder(); utxoBuilder.setOutPointHash(ByteString.copyFrom(utxo.getTxHash().getBytes())); utxoBuilder.setOutPointIndex((int) utxo.getIndex()); utxoBuilder.setScriptBytes(ByteString.copyFrom(utxo.getScriptBytes())); utxoBuilder.setValue(utxo.getValueLong()); if (utxo.isGenerated()) utxoBuilder.setIsGenerated(true); return utxoBuilder.build(); }