diff --git a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java
index 73740c63..0844ff3d 100644
--- a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java
+++ b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java
@@ -339,9 +339,11 @@ public class TransactionConfidence implements Serializable {
/**
* Called by the wallet when the tx appears on the best chain and a new block is added to the top. Updates the
* internal counter that tracks how deeply buried the block is.
+ *
+ * @return the new depth
*/
- public synchronized void incrementDepthInBlocks() {
- this.depth++;
+ public synchronized int incrementDepthInBlocks() {
+ return ++this.depth;
}
/**
@@ -365,6 +367,15 @@ public class TransactionConfidence implements Serializable {
this.depth = depth;
}
+ /**
+ * Erases the set of broadcast/seen peers. This cannot be called whilst the confidence is PENDING. It is useful
+ * for saving memory and wallet space once a tx is buried so deep it doesn't seem likely to go pending again.
+ */
+ public void clearBroadcastBy() {
+ checkState(getConfidenceType() != ConfidenceType.PENDING);
+ broadcastBy.clear();
+ }
+
/**
* If this transaction has been overridden by a double spend (is dead), this call returns the overriding transaction.
* Note that this call can return null if you have migrated an old wallet, as pre-Jan 2012 wallets did not
diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java
index 3295b356..0bb6ef63 100644
--- a/core/src/main/java/org/bitcoinj/core/Wallet.java
+++ b/core/src/main/java/org/bitcoinj/core/Wallet.java
@@ -1883,7 +1883,6 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
setLastBlockSeenHash(newBlockHash);
setLastBlockSeenHeight(block.getHeight());
setLastBlockSeenTimeSecs(block.getHeader().getTimeSeconds());
- // TODO: Clarify the code below.
// Notify all the BUILDING transactions of the new block.
// This is so that they can update their depth.
Set transactions = getTransactions(true);
@@ -1892,9 +1891,20 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// tx was already processed in receive() due to it appearing in this block, so we don't want to
// increment the tx confidence depth twice, it'd result in miscounting.
ignoreNextNewBlock.remove(tx.getHash());
- } else if (tx.getConfidence().getConfidenceType() == ConfidenceType.BUILDING) {
- tx.getConfidence().incrementDepthInBlocks();
- confidenceChanged.put(tx, TransactionConfidence.Listener.ChangeReason.DEPTH);
+ } else {
+ TransactionConfidence confidence = tx.getConfidence();
+ if (confidence.getConfidenceType() == ConfidenceType.BUILDING) {
+ // Erase the set of seen peers once the tx is so deep that it seems unlikely to ever go
+ // pending again. We could clear this data the moment a tx is seen in the block chain, but
+ // in cases where the chain re-orgs, this would mean that wallets would perceive a newly
+ // pending tx has zero confidence at all, which would not be right: we expect it to be
+ // included once again. We could have a separate was-in-chain-and-now-isn't confidence type
+ // but this way is backwards compatible with existing software, and the new state probably
+ // wouldn't mean anything different to just remembering peers anyway.
+ if (confidence.incrementDepthInBlocks() > 100)
+ confidence.clearBroadcastBy();
+ confidenceChanged.put(tx, TransactionConfidence.Listener.ChangeReason.DEPTH);
+ }
}
}