electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 8ec6a60daf7b0f3019677f27a20f59d311730c0f
parent 259c5c1b062960c85f6e946077a32be74f5ce137
Author: ThomasV <thomasv@gitorious>
Date:   Wed, 14 Nov 2012 15:33:44 +0100

compatibility with 0.6 protocol

Diffstat:
Mlib/gui_qt.py | 2++
Mlib/interface.py | 6++++++
Mlib/verifier.py | 14+++++++-------
Mlib/version.py | 2+-
Mlib/wallet.py | 84+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
5 files changed, 66 insertions(+), 42 deletions(-)

diff --git a/lib/gui_qt.py b/lib/gui_qt.py @@ -845,6 +845,8 @@ class ElectrumWindow(QMainWindow): label = self.wallet.labels.get(address,'') n = 0 h = self.wallet.history.get(address,[]) + if h == ['*']: h = [] + for tx_hash, tx_height in h: tx = self.wallet.transactions.get(tx_hash) if tx: n += 1 diff --git a/lib/interface.py b/lib/interface.py @@ -84,6 +84,12 @@ class Interface(threading.Thread): if error: print_error("received error:", c) + if msg_id is not None: + with self.lock: + method, params, channel = self.unanswered_requests.pop(msg_id) + response_queue = self.responses[channel] + response_queue.put({'method':method, 'params':params, 'error':error, 'id':msg_id}) + return if msg_id is not None: diff --git a/lib/verifier.py b/lib/verifier.py @@ -32,7 +32,7 @@ class WalletVerifier(threading.Thread): self.daemon = True self.config = config self.interface = interface - self.transactions = [] # monitored transactions + self.transactions = {} # monitored transactions self.interface.register_channel('verifier') self.verified_tx = config.get('verified_tx',{}) # height of verified tx @@ -49,16 +49,16 @@ class WalletVerifier(threading.Thread): def get_confirmations(self, tx): """ return the number of confirmations of a monitored transaction. """ with self.lock: - if tx in self.transactions: + if tx in self.transactions.keys(): return (self.local_height - self.verified_tx[tx] + 1) if tx in self.verified_tx else 0 else: return 0 - def add(self, tx_hash): + def add(self, tx_hash, tx_height): """ add a transaction to the list of monitored transactions. """ with self.lock: - if tx_hash not in self.transactions: - self.transactions.append(tx_hash) + if tx_hash not in self.transactions.keys(): + self.transactions[tx_hash] = tx_height def run(self): requested_merkle = [] @@ -87,11 +87,11 @@ class WalletVerifier(threading.Thread): # request missing tx if all_chunks: - for tx_hash in self.transactions: + for tx_hash, tx_height in self.transactions.items(): if tx_hash not in self.verified_tx: if self.merkle_roots.get(tx_hash) is None and tx_hash not in requested_merkle: print_error('requesting merkle', tx_hash) - self.interface.send([ ('blockchain.transaction.get_merkle',[tx_hash]) ], 'verifier') + self.interface.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], 'verifier') requested_merkle.append(tx_hash) # process pending headers diff --git a/lib/version.py b/lib/version.py @@ -1,4 +1,4 @@ ELECTRUM_VERSION = "1.3" # version of the client package -PROTOCOL_VERSION = '0.5' # protocol version requested +PROTOCOL_VERSION = '0.6' # protocol version requested SEED_VERSION = 4 # bump this everytime the seed generation is modified TRANSLATION_ID = 32150 # version of the wiki page diff --git a/lib/wallet.py b/lib/wallet.py @@ -381,7 +381,8 @@ class Wallet: addr = item.get('address') if addr in addresses: key = item['prevout_hash'] + ':%d'%item['prevout_n'] - value = self.prevout_values[ key ] + value = self.prevout_values.get( key ) + if value is None: continue v -= value for item in d.get('outputs'): addr = item.get('address') @@ -409,6 +410,7 @@ class Wallet: def get_addr_balance(self, addr): assert self.is_mine(addr) h = self.history.get(addr,[]) + if h == ['*']: return 0,0 c = u = 0 for tx_hash, tx_height in h: v = self.get_tx_value(tx_hash, [addr]) @@ -531,6 +533,7 @@ class Wallet: def get_status(self, h): if not h: return None + if h == ['*']: return '*' status = '' for tx_hash, height in h: status += tx_hash + ':%d:' % height @@ -553,16 +556,18 @@ class Wallet: def receive_history_callback(self, addr, hist): - if not self.check_new_history(addr, hist): - raise BaseException("error: received history for %s is not consistent with known transactions"%addr) + if hist != ['*']: + if not self.check_new_history(addr, hist): + raise BaseException("error: received history for %s is not consistent with known transactions"%addr) with self.lock: self.history[addr] = hist self.save() + + if hist != ['*']: for tx_hash, tx_height in hist: if tx_height>0: - self.verifier.add(tx_hash) - + self.verifier.add(tx_hash, tx_height) def get_tx_history(self): @@ -886,6 +891,7 @@ class Wallet: # set the timestamp for transactions that need it for hist in self.history.values(): + if hist == ['*']: continue for tx_hash, tx_height in hist: tx = self.transactions.get(tx_hash) if tx and not tx.get('timestamp'): @@ -894,7 +900,7 @@ class Wallet: self.set_tx_timestamp(tx_hash, timestamp) if tx_height>0: - self.verifier.add(tx_hash) + self.verifier.add(tx_hash, tx_height) @@ -936,6 +942,7 @@ class Wallet: # 1 check that tx is referenced in addr_history. addresses = [] for addr, hist in self.history.items(): + if hist == ['*']:continue for txh, height in hist: if txh == tx_hash: addresses.append(addr) @@ -998,6 +1005,7 @@ class WalletSynchronizer(threading.Thread): # request any missing transactions for history in self.wallet.history.values(): + if history == ['*']: continue for tx_hash, tx_height in history: if self.wallet.transactions.get(tx_hash) is None and (tx_hash, tx_height) not in missing_tx: missing_tx.append( (tx_hash, tx_height) ) @@ -1035,7 +1043,11 @@ class WalletSynchronizer(threading.Thread): # 3. handle response method = r['method'] params = r['params'] - result = r['result'] + result = r.get('result') + error = r.get('error') + if error: + print "error", r + continue if method == 'blockchain.address.subscribe': addr = params[0] @@ -1045,34 +1057,38 @@ class WalletSynchronizer(threading.Thread): elif method == 'blockchain.address.get_history': addr = params[0] - hist = [] - - # check that txids are unique - txids = [] - for item in result: - tx_hash = item['tx_hash'] - if tx_hash not in txids: - txids.append(tx_hash) - hist.append( (tx_hash, item['height']) ) - - if len(hist) != len(result): - raise BaseException("error: server sent history with non-unique txid") - - # check that the status corresponds to what was announced - if self.wallet.get_status(hist) != requested_histories.pop(addr): - raise BaseException("error: status mismatch: %s"%addr) + if result == ['*']: + assert requested_histories.pop(addr) == '*' + self.wallet.receive_history_callback(addr, result) + else: + hist = [] + # check that txids are unique + txids = [] + for item in result: + tx_hash = item['tx_hash'] + if tx_hash not in txids: + txids.append(tx_hash) + hist.append( (tx_hash, item['height']) ) + + if len(hist) != len(result): + raise BaseException("error: server sent history with non-unique txid") + + # check that the status corresponds to what was announced + rs = requested_histories.pop(addr) + if self.wallet.get_status(hist) != rs: + raise BaseException("error: status mismatch: %s"%addr) - # store received history - self.wallet.receive_history_callback(addr, hist) - - # request transactions that we don't have - for tx_hash, tx_height in hist: - if self.wallet.transactions.get(tx_hash) is None: - if (tx_hash, tx_height) not in requested_tx and (tx_hash, tx_height) not in missing_tx: - missing_tx.append( (tx_hash, tx_height) ) - else: - timestamp = self.wallet.verifier.get_timestamp(tx_height) - self.wallet.set_tx_timestamp(tx_hash, timestamp) + # store received history + self.wallet.receive_history_callback(addr, hist) + + # request transactions that we don't have + for tx_hash, tx_height in hist: + if self.wallet.transactions.get(tx_hash) is None: + if (tx_hash, tx_height) not in requested_tx and (tx_hash, tx_height) not in missing_tx: + missing_tx.append( (tx_hash, tx_height) ) + else: + timestamp = self.wallet.verifier.get_timestamp(tx_height) + self.wallet.set_tx_timestamp(tx_hash, timestamp) elif method == 'blockchain.transaction.get': tx_hash = params[0]