From 20f4ac96574dc7bdb811380ff948931663e19c44 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 30 Mar 2022 08:55:41 +0200 Subject: [PATCH] ensure unique stonewall input txids for entire tx (not just per set) --- .../drongo/wallet/StonewallUtxoSelector.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/StonewallUtxoSelector.java b/src/main/java/com/sparrowwallet/drongo/wallet/StonewallUtxoSelector.java index 64b2f64..0c3330d 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/StonewallUtxoSelector.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/StonewallUtxoSelector.java @@ -21,18 +21,31 @@ public class StonewallUtxoSelector implements UtxoSelector { public List> selectSets(long targetValue, Collection candidates) { long actualTargetValue = targetValue + noInputsFee; - List preferredCandidates = candidates.stream().filter(outputGroup -> outputGroup.getScriptType().equals(preferredScriptType)).collect(Collectors.toList()); + List uniqueCandidates = new ArrayList<>(); + for(OutputGroup candidate : candidates) { + OutputGroup existingTxGroup = getTransactionAlreadySelected(uniqueCandidates, candidate); + if(existingTxGroup != null) { + if(candidate.getValue() > existingTxGroup.getValue()) { + uniqueCandidates.remove(existingTxGroup); + uniqueCandidates.add(candidate); + } + } else { + uniqueCandidates.add(candidate); + } + } + + List preferredCandidates = uniqueCandidates.stream().filter(outputGroup -> outputGroup.getScriptType().equals(preferredScriptType)).collect(Collectors.toList()); List> preferredSets = selectSets(targetValue, preferredCandidates, actualTargetValue); if(!preferredSets.isEmpty()) { return preferredSets; } - return selectSets(targetValue, candidates, actualTargetValue); + return selectSets(targetValue, uniqueCandidates, actualTargetValue); } - private List> selectSets(long targetValue, Collection candidates, long actualTargetValue) { - for(int i = 0; i < 10; i++) { - List randomized = new ArrayList<>(candidates); + private List> selectSets(long targetValue, List uniqueCandidates, long actualTargetValue) { + for(int i = 0; i < 15; i++) { + List randomized = new ArrayList<>(uniqueCandidates); Collections.shuffle(randomized, random); List set1 = new ArrayList<>(); @@ -53,17 +66,7 @@ public class StonewallUtxoSelector implements UtxoSelector { long selectedValue = 0; while(selectedValue <= targetValue && !randomized.isEmpty()) { OutputGroup candidate = randomized.remove(0); - - OutputGroup existingTxGroup = getTransactionAlreadySelected(selectedSet, candidate); - if(existingTxGroup != null) { - if(candidate.getValue() > existingTxGroup.getValue()) { - selectedSet.remove(existingTxGroup); - selectedSet.add(candidate); - } - } else { - selectedSet.add(candidate); - } - + selectedSet.add(candidate); selectedValue = selectedSet.stream().mapToLong(OutputGroup::getEffectiveValue).sum(); }