From 7e98f9f79247b9991ca157343fc26f0fe1aa11af Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Sat, 16 Jan 2016 16:16:43 +0100 Subject: [PATCH] Wallet: Make transaction pools private again, but add a poolContainsTxHash() method that is visible for testing. --- .../main/java/org/bitcoinj/core/Wallet.java | 28 +++++++++++++--- .../org/bitcoinj/core/ChainSplitTest.java | 33 ++++++++++--------- .../java/org/bitcoinj/core/WalletTest.java | 10 +++--- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java index d7b2ab21..5e888e5b 100644 --- a/core/src/main/java/org/bitcoinj/core/Wallet.java +++ b/core/src/main/java/org/bitcoinj/core/Wallet.java @@ -120,10 +120,10 @@ public class Wallet extends BaseTaggableObject // to the user in the UI, etc). A transaction can leave dead and move into spent/unspent if there is a // re-org to a chain that doesn't include the double spend. - @VisibleForTesting final Map pending; - @VisibleForTesting final Map unspent; - @VisibleForTesting final Map spent; - @VisibleForTesting final Map dead; + private final Map pending; + private final Map unspent; + private final Map spent; + private final Map dead; // All transactions together. protected final Map transactions; @@ -2909,6 +2909,26 @@ public class Wallet extends BaseTaggableObject } } + @VisibleForTesting + public boolean poolContainsTxHash(final WalletTransaction.Pool pool, final Sha256Hash txHash) { + lock.lock(); + try { + switch (pool) { + case UNSPENT: + return unspent.containsKey(txHash); + case SPENT: + return spent.containsKey(txHash); + case PENDING: + return pending.containsKey(txHash); + case DEAD: + return dead.containsKey(txHash); + } + throw new RuntimeException("Unreachable"); + } finally { + lock.unlock(); + } + } + /** Returns a copy of the internal unspent outputs list */ public List getUnspents() { lock.lock(); diff --git a/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java b/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java index 1c14e267..c44f1828 100644 --- a/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java +++ b/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java @@ -25,6 +25,7 @@ import org.bitcoinj.testing.FakeTxBuilder; import org.bitcoinj.utils.BriefLogFormatter; import org.bitcoinj.utils.Threading; +import org.bitcoinj.wallet.WalletTransaction; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; @@ -586,10 +587,10 @@ public class ChainSplitTest { // Check the coinbase transaction is building and in the unspent pool only. final Transaction coinbase = txns.get(0); assertEquals(ConfidenceType.BUILDING, coinbase.getConfidence().getConfidenceType()); - assertTrue(!wallet.pending.containsKey(coinbase.getHash())); - assertTrue(wallet.unspent.containsKey(coinbase.getHash())); - assertTrue(!wallet.spent.containsKey(coinbase.getHash())); - assertTrue(!wallet.dead.containsKey(coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, coinbase.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.UNSPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.SPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.DEAD, coinbase.getHash())); // Add blocks to b3 until we can spend the coinbase. Block firstTip = b3; @@ -634,10 +635,10 @@ public class ChainSplitTest { // Transaction 1 (in block b2) is now on a side chain and should have confidence type of dead and be in // the dead pool only. assertEquals(TransactionConfidence.ConfidenceType.DEAD, coinbase.getConfidence().getConfidenceType()); - assertTrue(!wallet.pending.containsKey(coinbase.getHash())); - assertTrue(!wallet.unspent.containsKey(coinbase.getHash())); - assertTrue(!wallet.spent.containsKey(coinbase.getHash())); - assertTrue(wallet.dead.containsKey(coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.UNSPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.SPENT, coinbase.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.DEAD, coinbase.getHash())); assertTrue(fodderIsDead.get()); // ... and back to the first chain. @@ -656,10 +657,10 @@ public class ChainSplitTest { // The coinbase transaction should now have confidence type of building once more and in the unspent pool only. assertEquals(TransactionConfidence.ConfidenceType.BUILDING, coinbase.getConfidence().getConfidenceType()); - assertTrue(!wallet.pending.containsKey(coinbase.getHash())); - assertTrue(wallet.unspent.containsKey(coinbase.getHash())); - assertTrue(!wallet.spent.containsKey(coinbase.getHash())); - assertTrue(!wallet.dead.containsKey(coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, coinbase.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.UNSPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.SPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.DEAD, coinbase.getHash())); // However, fodder is still dead. Bitcoin Core doesn't keep killed transactions around in case they become // valid again later. They are just deleted from the mempool for good. @@ -679,9 +680,9 @@ public class ChainSplitTest { // The coinbase transaction should now have the confidence type of dead and be in the dead pool only. assertEquals(TransactionConfidence.ConfidenceType.DEAD, coinbase.getConfidence().getConfidenceType()); - assertTrue(!wallet.pending.containsKey(coinbase.getHash())); - assertTrue(!wallet.unspent.containsKey(coinbase.getHash())); - assertTrue(!wallet.spent.containsKey(coinbase.getHash())); - assertTrue(wallet.dead.containsKey(coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.UNSPENT, coinbase.getHash())); + assertTrue(!wallet.poolContainsTxHash(WalletTransaction.Pool.SPENT, coinbase.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.DEAD, coinbase.getHash())); } } diff --git a/core/src/test/java/org/bitcoinj/core/WalletTest.java b/core/src/test/java/org/bitcoinj/core/WalletTest.java index 1b6b5ebc..7451c47a 100644 --- a/core/src/test/java/org/bitcoinj/core/WalletTest.java +++ b/core/src/test/java/org/bitcoinj/core/WalletTest.java @@ -1156,27 +1156,27 @@ public class WalletTest extends TestWithWallet { private void assertInConflict(Transaction tx) { assertEquals(ConfidenceType.IN_CONFLICT, tx.getConfidence().getConfidenceType()); - assertTrue(wallet.pending.containsKey(tx.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, tx.getHash())); } private void assertPending(Transaction tx) { assertEquals(ConfidenceType.PENDING, tx.getConfidence().getConfidenceType()); - assertTrue(wallet.pending.containsKey(tx.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.PENDING, tx.getHash())); } private void assertSpent(Transaction tx) { assertEquals(ConfidenceType.BUILDING, tx.getConfidence().getConfidenceType()); - assertTrue(wallet.spent.containsKey(tx.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.SPENT, tx.getHash())); } private void assertUnspent(Transaction tx) { assertEquals(ConfidenceType.BUILDING, tx.getConfidence().getConfidenceType()); - assertTrue(wallet.unspent.containsKey(tx.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.UNSPENT, tx.getHash())); } private void assertDead(Transaction tx) { assertEquals(ConfidenceType.DEAD, tx.getConfidence().getConfidenceType()); - assertTrue(wallet.dead.containsKey(tx.getHash())); + assertTrue(wallet.poolContainsTxHash(WalletTransaction.Pool.DEAD, tx.getHash())); } @Test