3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 10:45:51 +00:00

Wallet.isConsistentOrThrow(): New variant of .isConsistent() that throws an exception describing the inconsistency.

This commit is contained in:
Andreas Schildbach 2016-02-16 20:44:43 +01:00
parent a1def190ad
commit b6c6d1213e

View File

@ -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() { 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(); lock.lock();
try { try {
boolean success = true;
Set<Transaction> transactions = getTransactions(true); Set<Transaction> transactions = getTransactions(true);
Set<Sha256Hash> hashes = new HashSet<Sha256Hash>(); Set<Sha256Hash> hashes = new HashSet<Sha256Hash>();
@ -1492,40 +1514,26 @@ public class Wallet extends BaseTaggableObject
} }
int size1 = transactions.size(); int size1 = transactions.size();
if (size1 != hashes.size()) { if (size1 != hashes.size()) {
log.error("Two transactions with same hash"); throw new IllegalStateException("Two transactions with same hash");
success = false;
} }
int size2 = unspent.size() + spent.size() + pending.size() + dead.size(); int size2 = unspent.size() + spent.size() + pending.size() + dead.size();
if (size1 != size2) { if (size1 != size2) {
log.error("Inconsistent wallet sizes: {} {}", size1, size2); throw new IllegalStateException("Inconsistent wallet sizes: " + size1 + ", " + size2);
success = false;
} }
for (Transaction tx : unspent.values()) { for (Transaction tx : unspent.values()) {
if (!isTxConsistent(tx, false)) { if (!isTxConsistent(tx, false)) {
success = false; throw new IllegalStateException("Inconsistent unspent tx: " + tx.getHashAsString());
log.error("Inconsistent unspent tx {}", tx.getHashAsString());
} }
} }
for (Transaction tx : spent.values()) { for (Transaction tx : spent.values()) {
if (!isTxConsistent(tx, true)) { if (!isTxConsistent(tx, true)) {
success = false; throw new IllegalStateException("Inconsistent spent tx: " + tx.getHashAsString());
log.error("Inconsistent spent tx {}", tx.getHashAsString());
} }
} }
if (!success) {
try {
log.error(toString());
} catch (RuntimeException x) {
log.error("Printing inconsistent wallet failed", x);
}
}
return success;
} finally { } finally {
lock.unlock(); lock.unlock();
} }
@ -1982,7 +1990,7 @@ public class Wallet extends BaseTaggableObject
} }
informConfidenceListenersIfNotReorganizing(); informConfidenceListenersIfNotReorganizing();
checkState(isConsistent()); isConsistentOrThrow();
// Optimization for the case where a block has tons of relevant transactions. // Optimization for the case where a block has tons of relevant transactions.
saveLater(); saveLater();
hardSaveOnNextBlock = true; hardSaveOnNextBlock = true;
@ -2426,7 +2434,7 @@ public class Wallet extends BaseTaggableObject
throw new RuntimeException(e); throw new RuntimeException(e);
} }
checkState(isConsistent()); isConsistentOrThrow();
informConfidenceListenersIfNotReorganizing(); informConfidenceListenersIfNotReorganizing();
saveNow(); saveNow();
} finally { } finally {
@ -3032,7 +3040,7 @@ public class Wallet extends BaseTaggableObject
} }
} }
if (dirty) { if (dirty) {
checkState(isConsistent()); isConsistentOrThrow();
saveLater(); saveLater();
} }
} finally { } finally {
@ -4708,7 +4716,7 @@ public class Wallet extends BaseTaggableObject
} }
notifyNewBestBlock(block); notifyNewBestBlock(block);
} }
checkState(isConsistent()); isConsistentOrThrow();
final Coin balance = getBalance(); final Coin balance = getBalance();
log.info("post-reorg balance is {}", balance.toFriendlyString()); log.info("post-reorg balance is {}", balance.toFriendlyString());
// Inform event listeners that a re-org took place. // Inform event listeners that a re-org took place.