mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 01:40:26 +01:00
More Wallet consistency checks
Conflicts: src/com/google/bitcoin/core/Wallet.java tools/src/main/java/com/google/bitcoin/tools/WalletTool.java
This commit is contained in:
parent
807914b9fd
commit
fa87176f62
@ -181,6 +181,29 @@ public class Transaction extends ChildMessage implements Serializable {
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* If isSpent - check that all my outputs spent, otherwise check that there at least
|
||||
* one unspent.
|
||||
*/
|
||||
boolean isConsistent(Wallet wallet, boolean isSpent) {
|
||||
boolean isActuallySpent = true;
|
||||
for (TransactionOutput o : outputs) {
|
||||
if (o.isAvailableForSpending()) {
|
||||
if (o.isMine(wallet)) isActuallySpent = false;
|
||||
if (o.getSpentBy() != null) {
|
||||
log.error("isAvailableForSpending != spentBy");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (o.getSpentBy() == null) {
|
||||
log.error("isAvailableForSpending != spentBy");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isActuallySpent == isSpent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the sum of the outputs that are sending coins to a key in the wallet.
|
||||
|
@ -206,29 +206,68 @@ public class Wallet implements Serializable {
|
||||
return loadFromFileStream(new FileInputStream(f));
|
||||
}
|
||||
|
||||
private boolean isConsistent() {
|
||||
public boolean isConsistent() {
|
||||
boolean success = true;
|
||||
// Pending and inactive can overlap, so merge them before counting
|
||||
HashSet<Transaction> pendingInactive = new HashSet<Transaction>();
|
||||
pendingInactive.addAll(pending.values());
|
||||
pendingInactive.addAll(inactive.values());
|
||||
|
||||
return getTransactions(true, true).size() ==
|
||||
unspent.size() + spent.size() + pendingInactive.size() + dead.size();
|
||||
Set<Transaction> transactions = getTransactions(true, true);
|
||||
|
||||
Set<Sha256Hash> hashes = new HashSet<Sha256Hash>();
|
||||
for (Transaction tx : transactions) {
|
||||
hashes.add(tx.getHash());
|
||||
}
|
||||
|
||||
int size1 = transactions.size();
|
||||
|
||||
if (size1 != hashes.size()) {
|
||||
log.error("Two transactions with same hash");
|
||||
success = false;
|
||||
}
|
||||
|
||||
int size2 = unspent.size() + spent.size() + pendingInactive.size() + dead.size();
|
||||
if (size1 != size2) {
|
||||
log.error("Inconsistent wallet sizes: {} {}", size1, size2);
|
||||
success = true;
|
||||
}
|
||||
|
||||
for (Transaction tx : unspent.values()) {
|
||||
if (!tx.isConsistent(this, false)) {
|
||||
success = false;
|
||||
log.error("Inconsistent unspent tx {}", tx.getHashAsString());
|
||||
}
|
||||
}
|
||||
|
||||
for (Transaction tx : spent.values()) {
|
||||
if (!tx.isConsistent(this, true)) {
|
||||
success = false;
|
||||
log.error("Inconsistent spent tx {}", tx.getHashAsString());
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wallet deserialized from the given input stream.
|
||||
*/
|
||||
public static Wallet loadFromFileStream(InputStream f) throws IOException {
|
||||
Wallet wallet;
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
ois = new ObjectInputStream(f);
|
||||
return (Wallet) ois.readObject();
|
||||
wallet = (Wallet) ois.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (ois != null) ois.close();
|
||||
}
|
||||
|
||||
if (!wallet.isConsistent())
|
||||
log.error("Loaded an inconsistent wallet");
|
||||
return wallet;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
|
Loading…
Reference in New Issue
Block a user