diff --git a/core/src/main/java/com/google/bitcoin/core/Wallet.java b/core/src/main/java/com/google/bitcoin/core/Wallet.java index 19a41323..acbeed4f 100644 --- a/core/src/main/java/com/google/bitcoin/core/Wallet.java +++ b/core/src/main/java/com/google/bitcoin/core/Wallet.java @@ -169,11 +169,12 @@ public class Wallet implements Serializable, BlockChainListener { public static class DefaultCoinSelector implements CoinSelector { public CoinSelection select(BigInteger biTarget, LinkedList candidates) { long target = biTarget.longValue(); - long total = 0; HashSet 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 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)) { Collections.sort(sortedOutputs, new Comparator() { public int compare(TransactionOutput a, TransactionOutput b) { @@ -183,18 +184,15 @@ public class Wallet implements Serializable, BlockChainListener { TransactionConfidence conf2 = b.parentTransaction.getConfidence(); if (conf1.getConfidenceType() == ConfidenceType.BUILDING) depth1 = conf1.getDepthInBlocks(); if (conf2.getConfidenceType() == ConfidenceType.BUILDING) depth2 = conf2.getDepthInBlocks(); - BigInteger aCoinDepth = a.getValue().multiply(BigInteger.valueOf(depth1)); - BigInteger bCoinDepth = b.getValue().multiply(BigInteger.valueOf(depth2)); - if (aCoinDepth.compareTo(bCoinDepth) < 0) - return 1; - else if (bCoinDepth.compareTo(aCoinDepth) < 0) - return -1; - // The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size - // (ie sort by reverse depth) - if (depth1 < depth2) - return -1; - else if (depth2 < depth1) - return 1; + BigInteger aValue = a.getValue(); + BigInteger bValue = b.getValue(); + BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1)); + BigInteger bCoinDepth = 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. + int c2 = bValue.compareTo(aValue); + if (c2 != 0) return c2; // They are entirely equivalent (possibly pending) so sort by hash to ensure a total ordering. BigInteger aHash = a.parentTransaction.getHash().toBigInteger(); BigInteger bHash = b.parentTransaction.getHash().toBigInteger(); @@ -204,6 +202,7 @@ public class Wallet implements Serializable, BlockChainListener { } // 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 (TransactionOutput output : sortedOutputs) { if (total >= target) break; // Only pick chain-included transactions, or transactions that are ours and pending.