tcheck that histories and transactions are consistent - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 62be41161bbc20bbfe085db9d24b3aec9b66348b DIR parent a48a971ae63b32ce94c1236c05d34d1b25219a84 HTML Author: ThomasV <thomasv@gitorious> Date: Wed, 7 Nov 2012 20:25:23 +0100 check that histories and transactions are consistent Diffstat: M lib/wallet.py | 82 ++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 12 deletions(-) --- DIR diff --git a/lib/wallet.py b/lib/wallet.py t@@ -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() t@@ -557,6 +566,7 @@ class Wallet: self.verifier.add(tx_hash) + def get_tx_history(self): with self.lock: lines = self.transactions.values() t@@ -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): t@@ -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: