mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-23 22:46:56 +01:00
Wallet: throw more appropriate exception types during completion.
Resolves issue 560.
This commit is contained in:
parent
028a1cca69
commit
b47995ed97
3 changed files with 19 additions and 14 deletions
|
@ -1884,6 +1884,11 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
return tx;
|
||||
}
|
||||
|
||||
public static class CompletionException extends RuntimeException {}
|
||||
public static class DustySendRequested extends CompletionException {}
|
||||
public static class CouldNotAdjustDownwards extends CompletionException {}
|
||||
public static class ExceededMaxTransactionSize extends CompletionException {}
|
||||
|
||||
/**
|
||||
* Given a spend request containing an incomplete transaction, makes it valid by adding outputs and signed inputs
|
||||
* according to the instructions in the request. The transaction in the request is modified by this method, as is
|
||||
|
@ -1891,8 +1896,10 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
*
|
||||
* @param req a SendRequest that contains the incomplete transaction and details for how to make it valid.
|
||||
* @throws InsufficientMoneyException if the request could not be completed due to not enough balance.
|
||||
* @throws IllegalArgumentException if you try and complete the same SendRequest twice, or if the given send request
|
||||
* cannot be completed without violating the protocol rules.
|
||||
* @throws IllegalArgumentException if you try and complete the same SendRequest twice
|
||||
* @throws DustySendRequested if the resultant transaction would violate the dust rules (an output that's too small to be worthwhile)
|
||||
* @throws CouldNotAdjustDownwards if emptying the wallet was requested and the output can't be shrunk for fees without violating a protocol rule.
|
||||
* @throws ExceededMaxTransactionSize if the resultant transaction is too big for Bitcoin to process (try breaking up the amounts of value)
|
||||
*/
|
||||
public void completeTx(SendRequest req) throws InsufficientMoneyException {
|
||||
lock.lock();
|
||||
|
@ -1925,7 +1932,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
for (TransactionOutput output : req.tx.getOutputs())
|
||||
if (output.getValue().compareTo(Utils.CENT) < 0) {
|
||||
if (output.getValue().compareTo(output.getMinNonDustValue()) < 0)
|
||||
throw new IllegalArgumentException("Tried to send dust with ensureMinRequiredFee set - no way to complete this");
|
||||
throw new DustySendRequested();
|
||||
needAtLeastReferenceFee = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1967,7 +1974,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
final BigInteger feePerKb = req.feePerKb == null ? BigInteger.ZERO : req.feePerKb;
|
||||
Transaction tx = req.tx;
|
||||
if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb))
|
||||
throw new InsufficientMoneyException.CouldNotAdjustDownwards();
|
||||
throw new CouldNotAdjustDownwards();
|
||||
}
|
||||
|
||||
totalInput = totalInput.add(bestCoinSelection.valueGathered);
|
||||
|
@ -1991,11 +1998,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
|
||||
// Check size.
|
||||
int size = req.tx.bitcoinSerialize().length;
|
||||
if (size > Transaction.MAX_STANDARD_TX_SIZE) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Transaction could not be created without exceeding max size: %d vs %d", size,
|
||||
Transaction.MAX_STANDARD_TX_SIZE));
|
||||
}
|
||||
if (size > Transaction.MAX_STANDARD_TX_SIZE)
|
||||
throw new ExceededMaxTransactionSize();
|
||||
|
||||
// Label the transaction as being self created. We can use this later to spend its change output even before
|
||||
// the transaction is confirmed. We deliberately won't bother notifying listeners here as there's not much
|
||||
|
|
|
@ -1463,7 +1463,7 @@ public class WalletTest extends TestWithWallet {
|
|||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = Wallet.ExceededMaxTransactionSize.class)
|
||||
public void respectMaxStandardSize() throws Exception {
|
||||
// Check that we won't create txns > 100kb. Average tx size is ~220 bytes so this would have to be enormous.
|
||||
sendMoneyToWallet(Utils.toNanoCoins(100, 0), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
|
@ -1498,11 +1498,12 @@ public class WalletTest extends TestWithWallet {
|
|||
Transaction tx3 = createFakeTx(params, BigInteger.TEN, myAddress);
|
||||
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2);
|
||||
|
||||
// No way we can add nearly enough fee
|
||||
// Not allowed to send dust.
|
||||
try {
|
||||
wallet.createSend(notMyAddr, BigInteger.ONE);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Wallet.DustySendRequested e) {
|
||||
// Expected.
|
||||
}
|
||||
// Spend it all without fee enforcement
|
||||
SendRequest req = SendRequest.to(notMyAddr, BigInteger.TEN.add(BigInteger.ONE.add(BigInteger.ONE)));
|
||||
|
@ -2179,7 +2180,7 @@ public class WalletTest extends TestWithWallet {
|
|||
try {
|
||||
wallet.completeTx(request);
|
||||
fail();
|
||||
} catch (InsufficientMoneyException.CouldNotAdjustDownwards e) {}
|
||||
} catch (Wallet.CouldNotAdjustDownwards e) {}
|
||||
request.ensureMinRequiredFee = false;
|
||||
wallet.completeTx(request);
|
||||
wallet.commitTx(request.tx);
|
||||
|
|
|
@ -87,7 +87,7 @@ public class Main extends Application {
|
|||
// last months worth or more (takes a few seconds).
|
||||
bitcoin.setCheckpoints(getClass().getResourceAsStream("checkpoints"));
|
||||
// As an example!
|
||||
bitcoin.useTor();
|
||||
// bitcoin.useTor();
|
||||
}
|
||||
|
||||
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
|
||||
|
|
Loading…
Add table
Reference in a new issue