Wallet: fix a couple of bugs.

1) TX confidence listeners were being run for chain height changes, even if they were not confirmed yet.

2) req.fee was being miscalculated for empty wallet transactions.
This commit is contained in:
Mike Hearn
2013-10-27 18:24:37 +01:00
parent a3356c511a
commit 16fb2f83eb
2 changed files with 17 additions and 8 deletions

View File

@@ -910,7 +910,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
// tx was already processed in receive() due to it appearing in this block, so we don't want to
// notify the tx confidence of work done twice, it'd result in miscounting.
ignoreNextNewBlock.remove(tx.getHash());
} else {
} else if (tx.getConfidence().getConfidenceType() == ConfidenceType.BUILDING) {
tx.getConfidence().notifyWorkDone(block.getHeader());
confidenceChanged.put(tx, TransactionConfidence.Listener.ChangeReason.DEPTH);
}
@@ -1770,8 +1770,8 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
}
BigInteger totalOutput = value;
log.info("Completing send tx with {} outputs totalling {} (not including fees)",
req.tx.getOutputs().size(), bitcoinValueToFriendlyString(value));
log.info("Completing send tx with {} outputs totalling {} satoshis (not including fees)",
req.tx.getOutputs().size(), value);
// If any inputs have already been added, we don't need to get their value from wallet
BigInteger totalInput = BigInteger.ZERO;
@@ -1816,6 +1816,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
feeCalculation = new FeeCalculation(req, value, originalInputs, needAtLeastReferenceFee, candidates);
} catch (InsufficientMoneyException e) {
// TODO: Propagate this after 0.9 is released and stop returning a boolean.
log.error("Insufficent money in wallet to pay the required fee");
return false;
}
bestCoinSelection = feeCalculation.bestCoinSelection;
@@ -1827,6 +1828,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector;
bestCoinSelection = selector.select(NetworkParameters.MAX_MONEY, candidates);
req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered);
totalOutput = bestCoinSelection.valueGathered;
}
for (TransactionOutput output : bestCoinSelection.gathered)
@@ -1836,8 +1838,10 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
final BigInteger baseFee = req.fee == null ? BigInteger.ZERO : req.fee;
final BigInteger feePerKb = req.feePerKb == null ? BigInteger.ZERO : req.feePerKb;
Transaction tx = req.tx;
if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb))
if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb)) {
log.error("Could not adjust output downwards to pay min fee.");
return false;
}
}
totalInput = totalInput.add(bestCoinSelection.valueGathered);
@@ -1865,9 +1869,8 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
int size = req.tx.bitcoinSerialize().length;
if (size > Transaction.MAX_STANDARD_TX_SIZE) {
// TODO: Throw an unchecked protocol exception here.
log.warn(String.format(
"Transaction could not be created without exceeding max size: %d vs %d",
size, Transaction.MAX_STANDARD_TX_SIZE));
log.error("Transaction could not be created without exceeding max size: {} vs {}", size,
Transaction.MAX_STANDARD_TX_SIZE);
return false;
}

View File

@@ -668,13 +668,19 @@ public class WalletTest extends TestWithWallet {
// However the confidence should be updated.
// Make a fresh copy of the tx to ensure we're testing realistically.
flags[0] = flags[1] = false;
final TransactionConfidence.Listener.ChangeReason[] reasons = new TransactionConfidence.Listener.ChangeReason[1];
notifiedTx[0].getConfidence().addEventListener(new TransactionConfidence.Listener() {
public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) {
flags[1] = true;
reasons[0] = reason;
}
});
assertEquals(TransactionConfidence.ConfidenceType.PENDING,
notifiedTx[0].getConfidence().getConfidenceType());
// Send a block with nothing interesting. Verify we don't get a callback.
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
Threading.waitForUserCode();
assertNull(reasons[0]);
final Transaction t1Copy = new Transaction(params, t1.bitcoinSerialize());
sendMoneyToWallet(t1Copy, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Threading.waitForUserCode();
@@ -689,7 +695,7 @@ public class WalletTest extends TestWithWallet {
wallet.receivePending(irrelevant, null);
Threading.waitForUserCode();
assertFalse(flags[0]);
assertEquals(2, walletChanged[0]);
assertEquals(3, walletChanged[0]);
}
@Test