mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-25 01:26:45 +00:00
fix high stonewall fee issue, add support for generalized transaction diagram
This commit is contained in:
parent
eb49c97133
commit
99440eda7f
4 changed files with 42 additions and 6 deletions
|
@ -165,6 +165,14 @@ public class Script {
|
|||
throw new ProtocolException("Script not a standard form that contains a single hash");
|
||||
}
|
||||
|
||||
public Address getToAddress() {
|
||||
try {
|
||||
return getToAddresses()[0];
|
||||
} catch(Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the destination address from this script, if it's in the required form.
|
||||
*/
|
||||
|
|
|
@ -7,13 +7,18 @@ public class Payment {
|
|||
private String label;
|
||||
private long amount;
|
||||
private boolean sendMax;
|
||||
private Type type = Type.DEFAULT;
|
||||
private Type type;
|
||||
|
||||
public Payment(Address address, String label, long amount, boolean sendMax) {
|
||||
this(address, label, amount, sendMax, Type.DEFAULT);
|
||||
}
|
||||
|
||||
public Payment(Address address, String label, long amount, boolean sendMax, Type type) {
|
||||
this.address = address;
|
||||
this.label = label;
|
||||
this.amount = amount;
|
||||
this.sendMax = sendMax;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
|
|
|
@ -518,6 +518,10 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
|||
return getWalletTxos().keySet().stream().anyMatch(ref -> ref.getHash().equals(txInput.getOutpoint().getHash()) && ref.getIndex() == txInput.getOutpoint().getIndex());
|
||||
}
|
||||
|
||||
public boolean isWalletTxo(TransactionOutput txOutput) {
|
||||
return getWalletTxos().keySet().stream().anyMatch(ref -> ref.getHash().equals(txOutput.getHash()) && ref.getIndex() == txOutput.getIndex());
|
||||
}
|
||||
|
||||
public boolean isWalletTxo(BlockTransactionHashIndex txo) {
|
||||
return getWalletTxos().containsKey(txo);
|
||||
}
|
||||
|
@ -771,7 +775,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
|||
List<Long> setChangeAmts = getSetChangeAmounts(selectedUtxoSets, totalPaymentAmount, noChangeFeeRequiredAmt);
|
||||
double noChangeFeeRate = (fee == null ? feeRate : noChangeFeeRequiredAmt / transaction.getVirtualSize());
|
||||
long costOfChangeAmt = getCostOfChange(noChangeFeeRate, longTermFeeRate);
|
||||
if(setChangeAmts.stream().allMatch(amt -> amt > costOfChangeAmt)) {
|
||||
if(setChangeAmts.stream().allMatch(amt -> amt > costOfChangeAmt) || (numSets > 1 && differenceAmt / transaction.getVirtualSize() > noChangeFeeRate * 2)) {
|
||||
//Change output is required, determine new fee once change output has been added
|
||||
WalletNode changeNode = getFreshNode(KeyPurpose.CHANGE);
|
||||
while(txExcludedChangeNodes.contains(changeNode)) {
|
||||
|
@ -796,7 +800,7 @@ public class Wallet extends Persistable implements Comparable<Wallet> {
|
|||
|
||||
if(setChangeAmts.stream().anyMatch(amt -> amt < costOfChangeAmt)) {
|
||||
//The new fee has meant that one of the change outputs is now dust. We pay too high a fee without change, but change is dust when added.
|
||||
if(numSets > 1) {
|
||||
if(numSets > 1 && differenceAmt / transaction.getVirtualSize() < noChangeFeeRate * 2) {
|
||||
//Maximize privacy. Pay a higher fee to keep multiple output sets.
|
||||
return new WalletTransaction(this, transaction, utxoSelectors, selectedUtxos, txPayments, differenceAmt);
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.sparrowwallet.drongo.wallet;
|
||||
|
||||
import com.sparrowwallet.drongo.address.Address;
|
||||
import com.sparrowwallet.drongo.protocol.Sha256Hash;
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
|
||||
|
@ -21,12 +22,17 @@ public class WalletTransaction {
|
|||
private final List<Payment> payments;
|
||||
private final Map<WalletNode, Long> changeMap;
|
||||
private final long fee;
|
||||
private final Map<Sha256Hash, BlockTransaction> inputTransactions;
|
||||
|
||||
public WalletTransaction(Wallet wallet, Transaction transaction, List<UtxoSelector> utxoSelectors, Map<BlockTransactionHashIndex, WalletNode> selectedUtxos, List<Payment> payments, long fee) {
|
||||
this(wallet, transaction, utxoSelectors, selectedUtxos, payments, Collections.emptyMap(), fee);
|
||||
}
|
||||
|
||||
public WalletTransaction(Wallet wallet, Transaction transaction, List<UtxoSelector> utxoSelectors, Map<BlockTransactionHashIndex, WalletNode> selectedUtxos, List<Payment> payments, Map<WalletNode, Long> changeMap, long fee) {
|
||||
this(wallet, transaction, utxoSelectors, selectedUtxos, payments, changeMap, fee, Collections.emptyMap());
|
||||
}
|
||||
|
||||
public WalletTransaction(Wallet wallet, Transaction transaction, List<UtxoSelector> utxoSelectors, Map<BlockTransactionHashIndex, WalletNode> selectedUtxos, List<Payment> payments, Map<WalletNode, Long> changeMap, long fee, Map<Sha256Hash, BlockTransaction> inputTransactions) {
|
||||
this.wallet = wallet;
|
||||
this.transaction = transaction;
|
||||
this.utxoSelectors = utxoSelectors;
|
||||
|
@ -34,6 +40,7 @@ public class WalletTransaction {
|
|||
this.payments = payments;
|
||||
this.changeMap = changeMap;
|
||||
this.fee = fee;
|
||||
this.inputTransactions = inputTransactions;
|
||||
}
|
||||
|
||||
public PSBT createPSBT() {
|
||||
|
@ -80,12 +87,16 @@ public class WalletTransaction {
|
|||
return selectedUtxos.keySet().stream().mapToLong(BlockTransactionHashIndex::getValue).sum();
|
||||
}
|
||||
|
||||
public Map<Sha256Hash, BlockTransaction> getInputTransactions() {
|
||||
return inputTransactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fee percentage matches the Coldcard implementation of total fee as a percentage of total value out
|
||||
* @return the fee percentage
|
||||
*/
|
||||
public double getFeePercentage() {
|
||||
return (double)getFee() / (getTotal() - getFee());
|
||||
return getFee() == 0 ? 0 : (double)getFee() / (getTotal() - getFee());
|
||||
}
|
||||
|
||||
public boolean isCoinControlUsed() {
|
||||
|
@ -97,11 +108,19 @@ public class WalletTransaction {
|
|||
}
|
||||
|
||||
public boolean isPremixSend(Payment payment) {
|
||||
return isWalletSend(getWallet().getChildWallet(StandardAccount.WHIRLPOOL_PREMIX), payment);
|
||||
return isWalletSend(StandardAccount.WHIRLPOOL_PREMIX, payment);
|
||||
}
|
||||
|
||||
public boolean isBadbankSend(Payment payment) {
|
||||
return isWalletSend(getWallet().getChildWallet(StandardAccount.WHIRLPOOL_BADBANK), payment);
|
||||
return isWalletSend(StandardAccount.WHIRLPOOL_BADBANK, payment);
|
||||
}
|
||||
|
||||
private boolean isWalletSend(StandardAccount childAccount, Payment payment) {
|
||||
if(getWallet() != null) {
|
||||
return isWalletSend(getWallet().getChildWallet(childAccount), payment);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isWalletSend(Wallet wallet, Payment payment) {
|
||||
|
|
Loading…
Reference in a new issue