diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java index 130c95fe..feecce41 100644 --- a/core/src/main/java/org/bitcoinj/core/Wallet.java +++ b/core/src/main/java/org/bitcoinj/core/Wallet.java @@ -1480,10 +1480,32 @@ public class Wallet extends BaseTaggableObject } } + /** + * Returns if this wallet is structurally consistent, so e.g. no duplicate transactions. First inconsistency and a + * dump of the wallet will be logged. + */ public boolean isConsistent() { + try { + isConsistentOrThrow(); + return true; + } catch (IllegalStateException x) { + log.error(x.getMessage()); + try { + log.error(toString()); + } catch (RuntimeException x2) { + log.error("Printing inconsistent wallet failed", x2); + } + return false; + } + } + + /** + * Variant of {@link Wallet#isConsistent()} that throws an {@link IllegalStateException} describing the first + * inconsistency. + */ + public void isConsistentOrThrow() throws IllegalStateException { lock.lock(); try { - boolean success = true; Set transactions = getTransactions(true); Set hashes = new HashSet(); @@ -1492,40 +1514,26 @@ public class Wallet extends BaseTaggableObject } int size1 = transactions.size(); - if (size1 != hashes.size()) { - log.error("Two transactions with same hash"); - success = false; + throw new IllegalStateException("Two transactions with same hash"); } int size2 = unspent.size() + spent.size() + pending.size() + dead.size(); if (size1 != size2) { - log.error("Inconsistent wallet sizes: {} {}", size1, size2); - success = false; + throw new IllegalStateException("Inconsistent wallet sizes: " + size1 + ", " + size2); } for (Transaction tx : unspent.values()) { if (!isTxConsistent(tx, false)) { - success = false; - log.error("Inconsistent unspent tx {}", tx.getHashAsString()); + throw new IllegalStateException("Inconsistent unspent tx: " + tx.getHashAsString()); } } for (Transaction tx : spent.values()) { if (!isTxConsistent(tx, true)) { - success = false; - log.error("Inconsistent spent tx {}", tx.getHashAsString()); + throw new IllegalStateException("Inconsistent spent tx: " + tx.getHashAsString()); } } - - if (!success) { - try { - log.error(toString()); - } catch (RuntimeException x) { - log.error("Printing inconsistent wallet failed", x); - } - } - return success; } finally { lock.unlock(); } @@ -1982,7 +1990,7 @@ public class Wallet extends BaseTaggableObject } informConfidenceListenersIfNotReorganizing(); - checkState(isConsistent()); + isConsistentOrThrow(); // Optimization for the case where a block has tons of relevant transactions. saveLater(); hardSaveOnNextBlock = true; @@ -2426,7 +2434,7 @@ public class Wallet extends BaseTaggableObject throw new RuntimeException(e); } - checkState(isConsistent()); + isConsistentOrThrow(); informConfidenceListenersIfNotReorganizing(); saveNow(); } finally { @@ -3032,7 +3040,7 @@ public class Wallet extends BaseTaggableObject } } if (dirty) { - checkState(isConsistent()); + isConsistentOrThrow(); saveLater(); } } finally { @@ -4708,7 +4716,7 @@ public class Wallet extends BaseTaggableObject } notifyNewBestBlock(block); } - checkState(isConsistent()); + isConsistentOrThrow(); final Coin balance = getBalance(); log.info("post-reorg balance is {}", balance.toFriendlyString()); // Inform event listeners that a re-org took place.