electrum

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

commit 2c0f894e7681c14886061501c4c4dd6bd9346830
parent 082d676799a557e026a856b1a8bb8c11af04c11c
Author: ThomasV <thomasv@gitorious>
Date:   Fri, 23 Nov 2012 18:36:02 +0100

Merge branch 'master' of git://github.com/spesmilo/electrum

Diffstat:
Melectrum | 7++++---
Mlib/wallet.py | 84++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 68 insertions(+), 23 deletions(-)

diff --git a/electrum b/electrum @@ -121,7 +121,7 @@ def prompt_password(prompt, confirm=True): password = None return password -def parse_args(): +def arg_parser(): usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands)) parser = optparse.OptionParser(prog=usage) parser.add_option("-g", "--gui", dest="gui", help="User interface: qt, lite, gtk or text") @@ -136,12 +136,13 @@ def parse_args(): parser.add_option("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is t or h") parser.add_option("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http") parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="show debugging information") - return parser.parse_args() + return parser if __name__ == '__main__': - options, args = parse_args() + parser = arg_parser() + options, args = parser.parse_args() set_verbosity(options.verbose) # config is an object passed to the various constructors (wallet, interface, gui) diff --git a/lib/wallet.py b/lib/wallet.py @@ -414,7 +414,11 @@ class Wallet: else: # some inputs are mine: fee = None - v = v_out_mine - v_in + if is_send: + v = v_out_mine - v_out + else: + # no input is mine + v = v_out_mine return is_send, v, fee @@ -438,7 +442,7 @@ class Wallet: + "Status: %d confirmations\n"%conf if is_mine: if fee: - tx_details += "Amount sent: %s\n"% format_satoshis(v+fee, False) \ + tx_details += "Amount sent: %s\n"% format_satoshis(v-fee, False) \ + "Transaction fee: %s\n"% format_satoshis(fee, False) else: tx_details += "Amount sent: %s\n"% format_satoshis(v, False) \ @@ -554,6 +558,7 @@ class Wallet: h = self.history.get(addr, []) if h == ['*']: continue for tx_hash, tx_height in h: + tx = self.transactions.get(tx_hash) for output in tx.get('outputs'): if output.get('address') != addr: continue key = tx_hash + ":%d" % output.get('index') @@ -654,9 +659,8 @@ class Wallet: def receive_history_callback(self, addr, hist): - if hist != ['*']: - if not self.check_new_history(addr, hist): - raise BaseException("error: received history for %s is not consistent with known transactions"%addr) + 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 @@ -696,12 +700,9 @@ class Wallet: tx_hash = tx['tx_hash'] timestamp = tx.get('timestamp') conf = self.verifier.get_confirmations(tx_hash) if self.verifier else None - is_mine, v, fee = self.get_tx_value(tx_hash) - if v is not None: - balance += v - value = v + fee if fee is not None else v - else: - value = None + is_mine, value, fee = self.get_tx_value(tx_hash) + if value is not None: + balance += value result.append( (tx_hash, conf, is_mine, value, fee, balance, timestamp) ) @@ -1068,15 +1069,58 @@ class Wallet: 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 + + # check that all tx in hist are relevant + if hist != ['*']: + 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 + + # check that we are not "orphaning" a transaction + old_hist = self.history.get(addr,[]) + if old_hist == ['*']: return True + + for tx_hash, height in old_hist: + if tx_hash in map(lambda x:x[0], hist): continue + found = False + for _addr, _hist in self.history.items(): + if _addr == addr: continue + if _hist == ['*']: continue + _tx_hist = map(lambda x:x[0], _hist) + if tx_hash in _tx_hist: + found = True + break + + if not found: + tx = self.transactions.get(tx_hash) + # already verified? + if tx.get('height'): + continue + # unconfirmed tx + print_error("new history is orphaning transaction:", tx_hash) + # check that all outputs are not mine, request histories + ext_requests = [] + for o in tx.get('outputs'): + _addr = o.get('address') + assert not self.is_mine(_addr) + ext_requests.append( ('blockchain.address.get_history', [_addr]) ) + + ext_h = self.interface.synchronous_get(ext_requests) + height = None + for h in ext_h: + if h == ['*']: continue + for item in h: + if item.get('tx_hash') == tx_hash: + height = item.get('height') + tx['height'] = height + if height: + print_error("found height for", tx_hash, height) + self.verifier.add(tx_hash, height) + else: + print_error("removing orphaned tx from history", tx_hash) + self.transactions.pop(tx_hash) return True