check that histories and transactions are consistent

This commit is contained in:
ThomasV 2012-11-07 20:25:23 +01:00
parent a48a971ae6
commit 62be41161b
1 changed files with 70 additions and 12 deletions

View File

@ -538,17 +538,26 @@ class Wallet:
def receive_tx_callback(self, tx_hash, d):
#print "updating history for", addr
#with self.lock:
self.transactions[tx_hash] = d
def receive_tx_callback(self, tx_hash, tx):
if not self.check_new_tx(tx_hash, tx):
print "error: transaction not consistent with history", tx_hash
return
with self.lock:
self.transactions[tx_hash] = tx
self.update_tx_outputs(tx_hash)
self.save()
def receive_history_callback(self, addr, hist):
#print "updating history for", addr
if not self.check_new_history(addr, hist):
print "error: history check failed", tx_hash
return
with self.lock:
self.history[addr] = hist
self.save()
@ -557,6 +566,7 @@ class Wallet:
self.verifier.add(tx_hash)
def get_tx_history(self):
with self.lock:
lines = self.transactions.values()
@ -896,6 +906,53 @@ class Wallet:
def is_addr_in_tx(self, addr, tx):
found = False
for txin in tx.get('inputs'):
if addr == txin.get('address'):
found = True
break
for txout in tx.get('outputs'):
if addr == txout.get('address'):
found = True
break
return found
def check_new_history(self, addr, hist):
# - check that all tx in hist are relevant
for tx_hash, height in hist:
tx = self.transactions.get(tx_hash)
if not tx: continue
if not self.is_addr_in_tx(addr,tx):
return False
# todo: check that we are not "orphaning" a transaction
# if we are, reject tx if unconfirmed, else reject the server
return True
def check_new_tx(self, tx_hash, tx):
# 1 check that tx is referenced in addr_history.
addresses = []
for addr, hist in self.history.items():
for txh, height in hist:
if txh == tx_hash:
addresses.append(addr)
if not addresses:
return False
# 2 check that referencing addresses are in the tx
for addr in addresses:
if not self.is_addr_in_tx(addr, tx):
return False
return True
class WalletSynchronizer(threading.Thread):
@ -915,19 +972,20 @@ class WalletSynchronizer(threading.Thread):
new_addresses = self.wallet.synchronize()
if new_addresses:
self.subscribe_to_addresses(new_addresses)
self.wallet.up_to_date = False
return
if self.interface.is_up_to_date('synchronizer'):
if not self.wallet.up_to_date:
self.wallet.up_to_date = True
self.was_updated = True
self.wallet.up_to_date_event.set()
else:
if not self.interface.is_up_to_date('synchronizer'):
if self.wallet.up_to_date:
self.wallet.up_to_date = False
self.was_updated = True
return
self.wallet.up_to_date = True
self.was_updated = True
self.wallet.up_to_date_event.set()
def subscribe_to_addresses(self, addresses):
messages = []
for addr in addresses: