mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-26 18:16:45 +00:00
add utxo filters
This commit is contained in:
parent
b2297a8d02
commit
e8d8fa6126
3 changed files with 49 additions and 8 deletions
|
@ -0,0 +1,31 @@
|
||||||
|
package com.sparrowwallet.drongo.wallet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class ExcludeUtxoFilter implements UtxoFilter {
|
||||||
|
private final Collection<BlockTransactionHashIndex> excludedUtxos;
|
||||||
|
|
||||||
|
public ExcludeUtxoFilter() {
|
||||||
|
this.excludedUtxos = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExcludeUtxoFilter(Collection<BlockTransactionHashIndex> excludedUtxos) {
|
||||||
|
this.excludedUtxos = new ArrayList<>(excludedUtxos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEligible(BlockTransactionHashIndex candidate) {
|
||||||
|
for(BlockTransactionHashIndex excludedUtxo : excludedUtxos) {
|
||||||
|
if(candidate.getHash().equals(excludedUtxo.getHash()) && candidate.getIndex() == excludedUtxo.getIndex()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<BlockTransactionHashIndex> getExcludedUtxos() {
|
||||||
|
return excludedUtxos;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.sparrowwallet.drongo.wallet;
|
||||||
|
|
||||||
|
public interface UtxoFilter {
|
||||||
|
boolean isEligible(BlockTransactionHashIndex candidate);
|
||||||
|
}
|
|
@ -424,11 +424,11 @@ public class Wallet {
|
||||||
return getFee(changeOutput, feeRate, longTermFeeRate);
|
return getFee(changeOutput, feeRate, longTermFeeRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WalletTransaction createWalletTransaction(List<UtxoSelector> utxoSelectors, Address recipientAddress, long recipientAmount, double feeRate, double longTermFeeRate, Long fee, Integer currentBlockHeight, boolean sendAll, boolean groupByAddress, boolean includeMempoolChange) throws InsufficientFundsException {
|
public WalletTransaction createWalletTransaction(List<UtxoSelector> utxoSelectors, List<UtxoFilter> utxoFilters, Address recipientAddress, long recipientAmount, double feeRate, double longTermFeeRate, Long fee, Integer currentBlockHeight, boolean sendAll, boolean groupByAddress, boolean includeMempoolChange) throws InsufficientFundsException {
|
||||||
long valueRequiredAmt = recipientAmount;
|
long valueRequiredAmt = recipientAmount;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
Map<BlockTransactionHashIndex, WalletNode> selectedUtxos = selectInputs(utxoSelectors, valueRequiredAmt, feeRate, longTermFeeRate, groupByAddress, includeMempoolChange);
|
Map<BlockTransactionHashIndex, WalletNode> selectedUtxos = selectInputs(utxoSelectors, utxoFilters, valueRequiredAmt, feeRate, longTermFeeRate, groupByAddress, includeMempoolChange);
|
||||||
long totalSelectedAmt = selectedUtxos.keySet().stream().mapToLong(BlockTransactionHashIndex::getValue).sum();
|
long totalSelectedAmt = selectedUtxos.keySet().stream().mapToLong(BlockTransactionHashIndex::getValue).sum();
|
||||||
|
|
||||||
Transaction transaction = new Transaction();
|
Transaction transaction = new Transaction();
|
||||||
|
@ -513,8 +513,8 @@ public class Wallet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<BlockTransactionHashIndex, WalletNode> selectInputs(List<UtxoSelector> utxoSelectors, Long targetValue, double feeRate, double longTermFeeRate, boolean groupByAddress, boolean includeMempoolChange) throws InsufficientFundsException {
|
private Map<BlockTransactionHashIndex, WalletNode> selectInputs(List<UtxoSelector> utxoSelectors, List<UtxoFilter> utxoFilters, Long targetValue, double feeRate, double longTermFeeRate, boolean groupByAddress, boolean includeMempoolChange) throws InsufficientFundsException {
|
||||||
List<OutputGroup> utxoPool = getGroupedUtxos(feeRate, longTermFeeRate, groupByAddress);
|
List<OutputGroup> utxoPool = getGroupedUtxos(utxoFilters, feeRate, longTermFeeRate, groupByAddress);
|
||||||
|
|
||||||
List<OutputGroup.Filter> filters = new ArrayList<>();
|
List<OutputGroup.Filter> filters = new ArrayList<>();
|
||||||
filters.add(new OutputGroup.Filter(1, 6));
|
filters.add(new OutputGroup.Filter(1, 6));
|
||||||
|
@ -540,17 +540,22 @@ public class Wallet {
|
||||||
throw new InsufficientFundsException("Not enough combined value in UTXOs for output value " + targetValue);
|
throw new InsufficientFundsException("Not enough combined value in UTXOs for output value " + targetValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<OutputGroup> getGroupedUtxos(double feeRate, double longTermFeeRate, boolean groupByAddress) {
|
private List<OutputGroup> getGroupedUtxos(List<UtxoFilter> utxoFilters, double feeRate, double longTermFeeRate, boolean groupByAddress) {
|
||||||
List<OutputGroup> outputGroups = new ArrayList<>();
|
List<OutputGroup> outputGroups = new ArrayList<>();
|
||||||
getGroupedUtxos(outputGroups, getNode(KeyPurpose.RECEIVE), feeRate, longTermFeeRate, groupByAddress);
|
getGroupedUtxos(outputGroups, getNode(KeyPurpose.RECEIVE), utxoFilters, feeRate, longTermFeeRate, groupByAddress);
|
||||||
getGroupedUtxos(outputGroups, getNode(KeyPurpose.CHANGE), feeRate, longTermFeeRate, groupByAddress);
|
getGroupedUtxos(outputGroups, getNode(KeyPurpose.CHANGE), utxoFilters, feeRate, longTermFeeRate, groupByAddress);
|
||||||
return outputGroups;
|
return outputGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getGroupedUtxos(List<OutputGroup> outputGroups, WalletNode purposeNode, double feeRate, double longTermFeeRate, boolean groupByAddress) {
|
private void getGroupedUtxos(List<OutputGroup> outputGroups, WalletNode purposeNode, List<UtxoFilter> utxoFilters, double feeRate, double longTermFeeRate, boolean groupByAddress) {
|
||||||
for(WalletNode addressNode : purposeNode.getChildren()) {
|
for(WalletNode addressNode : purposeNode.getChildren()) {
|
||||||
OutputGroup outputGroup = null;
|
OutputGroup outputGroup = null;
|
||||||
for(BlockTransactionHashIndex utxo : addressNode.getUnspentTransactionOutputs()) {
|
for(BlockTransactionHashIndex utxo : addressNode.getUnspentTransactionOutputs()) {
|
||||||
|
Optional<UtxoFilter> matchedFilter = utxoFilters.stream().filter(utxoFilter -> !utxoFilter.isEligible(utxo)).findAny();
|
||||||
|
if(matchedFilter.isPresent()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(outputGroup == null || !groupByAddress) {
|
if(outputGroup == null || !groupByAddress) {
|
||||||
outputGroup = new OutputGroup(getStoredBlockHeight(), getInputWeightUnits(), feeRate, longTermFeeRate);
|
outputGroup = new OutputGroup(getStoredBlockHeight(), getInputWeightUnits(), feeRate, longTermFeeRate);
|
||||||
outputGroups.add(outputGroup);
|
outputGroups.add(outputGroup);
|
||||||
|
|
Loading…
Reference in a new issue