mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-01-30 23:02:15 +00:00
Consider age of outputs when creating spends.
This commit is contained in:
parent
757334da80
commit
e99e4bd63c
@ -221,9 +221,30 @@ public class Wallet implements Serializable, BlockChainListener {
|
|||||||
long target = biTarget.longValue();
|
long target = biTarget.longValue();
|
||||||
long total = 0;
|
long total = 0;
|
||||||
LinkedList<TransactionOutput> selected = Lists.newLinkedList();
|
LinkedList<TransactionOutput> selected = Lists.newLinkedList();
|
||||||
// Super dumb algorithm: just iterate through candidates and keep adding them in whatever order until we
|
// Sort the inputs by age so we use oldest first.
|
||||||
// have enough.
|
// TODO: Consider changing the wallets internal format to track just outputs and keep them ordered.
|
||||||
for (TransactionOutput output : candidates) {
|
ArrayList<TransactionOutput> sortedOutputs = new ArrayList<TransactionOutput>(candidates);
|
||||||
|
Collections.sort(sortedOutputs, new Comparator<TransactionOutput>() {
|
||||||
|
public int compare(TransactionOutput a, TransactionOutput b) {
|
||||||
|
int depth1 = 0;
|
||||||
|
int depth2 = 0;
|
||||||
|
TransactionConfidence conf1 = a.parentTransaction.getConfidence();
|
||||||
|
TransactionConfidence conf2 = b.parentTransaction.getConfidence();
|
||||||
|
if (conf1.getConfidenceType() == ConfidenceType.BUILDING) depth1 = conf1.getDepthInBlocks();
|
||||||
|
if (conf2.getConfidenceType() == ConfidenceType.BUILDING) depth2 = conf2.getDepthInBlocks();
|
||||||
|
if (depth1 < depth2)
|
||||||
|
return 1;
|
||||||
|
else if (depth1 > depth2)
|
||||||
|
return -1;
|
||||||
|
// Their depths are equal (possibly pending) so sort by hash to ensure a total ordering.
|
||||||
|
BigInteger aHash = a.parentTransaction.getHash().toBigInteger();
|
||||||
|
BigInteger bHash = b.parentTransaction.getHash().toBigInteger();
|
||||||
|
return aHash.compareTo(bHash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Now iterate over the sorted outputs until we have got as close to the target as possible or a little
|
||||||
|
// bit over (excessive value will be change).
|
||||||
|
for (TransactionOutput output : sortedOutputs) {
|
||||||
if (total >= target) break;
|
if (total >= target) break;
|
||||||
// Only pick chain-included transactions, or transactions that are ours and pending.
|
// Only pick chain-included transactions, or transactions that are ours and pending.
|
||||||
TransactionConfidence confidence = output.parentTransaction.getConfidence();
|
TransactionConfidence confidence = output.parentTransaction.getConfidence();
|
||||||
|
@ -866,6 +866,23 @@ public class WalletTest {
|
|||||||
assertFalse(o2.isAvailableForSpending());
|
assertFalse(o2.isAvailableForSpending());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ageMattersDuringSelection() throws Exception {
|
||||||
|
// Test that we prefer older coins to newer coins when building spends. This reduces required fees and improves
|
||||||
|
// time to confirmation as the transaction will appear less spammy.
|
||||||
|
final int ITERATIONS = 10;
|
||||||
|
Transaction[] txns = new Transaction[ITERATIONS];
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
txns[i] = sendMoneyToWallet(Utils.toNanoCoins(1, 0), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||||
|
}
|
||||||
|
// Check that we spend transactions in order of reception.
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
Transaction spend = wallet.createSend(new ECKey().toAddress(params), Utils.toNanoCoins(1, 0));
|
||||||
|
assertEquals("Failed on iteration " + i, spend.getInput(0).getOutpoint().getHash(), txns[i].getHash());
|
||||||
|
wallet.commitTx(spend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// There is a test for spending a coinbase transaction as it matures in BlockChainTest#coinbaseTransactionAvailability
|
// There is a test for spending a coinbase transaction as it matures in BlockChainTest#coinbaseTransactionAvailability
|
||||||
|
|
||||||
// Support for offline spending is tested in PeerGroupTest
|
// Support for offline spending is tested in PeerGroupTest
|
||||||
|
Loading…
Reference in New Issue
Block a user