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:
M | electrum | | | 7 | ++++--- |
M | lib/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