TransactionOutput: New isDust() method, and use it.

This commit is contained in:
Andreas Schildbach
2016-03-12 20:50:57 +01:00
parent 78ae8a0bd7
commit 90d8c151be
5 changed files with 22 additions and 15 deletions

View File

@@ -205,6 +205,16 @@ public class TransactionOutput extends ChildMessage {
throw new IllegalStateException("Output linked to wrong parent transaction?");
}
/**
* Will this transaction be relayable and mined by default miners?
*/
public boolean isDust() {
// Transactions that are OP_RETURN can't be dust regardless of their value.
if (getScriptPubKey().isOpReturn())
return false;
return getValue().isLessThan(getMinNonDustValue());
}
/**
* <p>Gets the minimum value for a txout of this size to be considered non-dust by Bitcoin Core
* (and thus relayed). See: CTxOut::IsDust() in Bitcoin Core. The assumption is that any output that would

View File

@@ -4119,15 +4119,12 @@ public class Wallet extends BaseTaggableObject
for (TransactionOutput output : req.tx.getOutputs()) {
if (output.getValue().compareTo(Coin.CENT) < 0) {
needAtLeastReferenceFee = true;
if (output.getValue().compareTo(output.getMinNonDustValue()) < 0) { // Is transaction a "dust".
if (output.getScriptPubKey().isOpReturn()) { // Transactions that are OP_RETURN can't be dust regardless of their value.
++opReturnCount;
continue;
} else {
throw new DustySendRequested();
}
}
break;
if (output.isDust())
throw new DustySendRequested();
if (output.getScriptPubKey().isOpReturn())
++opReturnCount;
else
break;
}
}
}
@@ -4277,7 +4274,7 @@ public class Wallet extends BaseTaggableObject
fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
TransactionOutput output = tx.getOutput(0);
output.setValue(output.getValue().subtract(fee));
return output.getMinNonDustValue().compareTo(output.getValue()) <= 0;
return !output.isDust();
}
/**
@@ -5084,11 +5081,11 @@ public class Wallet extends BaseTaggableObject
changeAddress = currentChangeAddress();
changeOutput = new TransactionOutput(params, req.tx, change, changeAddress);
// If the change output would result in this transaction being rejected as dust, just drop the change and make it a fee
if (req.ensureMinRequiredFee && change.isLessThan(Transaction.MIN_NONDUST_OUTPUT)) {
if (req.ensureMinRequiredFee && changeOutput.isDust()) {
// This solution definitely fits in category 3
isCategory3 = true;
additionalValueForNextCategory = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(
Transaction.MIN_NONDUST_OUTPUT.add(Coin.SATOSHI));
changeOutput.getMinNonDustValue().add(Coin.SATOSHI));
} else {
size += changeOutput.unsafeBitcoinSerialize().length + VarInt.sizeOf(req.tx.getOutputs().size()) - VarInt.sizeOf(req.tx.getOutputs().size() - 1);
// This solution is either category 1 or 2

View File

@@ -250,7 +250,7 @@ public abstract class PaymentChannelServerState {
Wallet.SendRequest req = makeUnsignedChannelContract(newValueToMe);
if (!fullyUsedUp && refundSize.compareTo(req.tx.getOutput(0).getMinNonDustValue()) < 0)
if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");
// Get the wallet's copy of the contract (ie with confidence information), if this is null, the wallet

View File

@@ -134,7 +134,7 @@ public class PaymentChannelV1ClientState extends PaymentChannelClientState {
// format which one is the change. If we start obfuscating the change output better in future this may
// be worth revisiting.
TransactionOutput multisigOutput = template.addOutput(totalValue, ScriptBuilder.createMultiSigOutputScript(2, keys));
if (multisigOutput.getMinNonDustValue().compareTo(totalValue) > 0)
if (multisigOutput.isDust())
throw new ValueOutOfRangeException("totalValue too small to use");
Wallet.SendRequest req = Wallet.SendRequest.forTx(template);
req.coinSelector = AllowUnconfirmedCoinSelector.get();

View File

@@ -110,7 +110,7 @@ public class PaymentChannelV2ClientState extends PaymentChannelClientState {
ScriptBuilder.createCLTVPaymentChannelOutput(BigInteger.valueOf(expiryTime), myKey, serverKey);
TransactionOutput transactionOutput = template.addOutput(totalValue,
ScriptBuilder.createP2SHOutputScript(redeemScript));
if (transactionOutput.getMinNonDustValue().compareTo(totalValue) > 0)
if (transactionOutput.isDust())
throw new ValueOutOfRangeException("totalValue too small to use");
Wallet.SendRequest req = Wallet.SendRequest.forTx(template);
req.coinSelector = AllowUnconfirmedCoinSelector.get();