Merge branch 'master' of git://github.com/spesmilo/electrum
This commit is contained in:
7
electrum
7
electrum
@@ -121,7 +121,7 @@ def prompt_password(prompt, confirm=True):
|
|||||||
password = None
|
password = None
|
||||||
return password
|
return password
|
||||||
|
|
||||||
def parse_args():
|
def arg_parser():
|
||||||
usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands))
|
usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands))
|
||||||
parser = optparse.OptionParser(prog=usage)
|
parser = optparse.OptionParser(prog=usage)
|
||||||
parser.add_option("-g", "--gui", dest="gui", help="User interface: qt, lite, gtk or text")
|
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("-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("-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")
|
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__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
options, args = parse_args()
|
parser = arg_parser()
|
||||||
|
options, args = parser.parse_args()
|
||||||
set_verbosity(options.verbose)
|
set_verbosity(options.verbose)
|
||||||
|
|
||||||
# config is an object passed to the various constructors (wallet, interface, gui)
|
# config is an object passed to the various constructors (wallet, interface, gui)
|
||||||
|
|||||||
@@ -414,7 +414,11 @@ class Wallet:
|
|||||||
else:
|
else:
|
||||||
# some inputs are mine:
|
# some inputs are mine:
|
||||||
fee = None
|
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
|
return is_send, v, fee
|
||||||
|
|
||||||
@@ -438,7 +442,7 @@ class Wallet:
|
|||||||
+ "Status: %d confirmations\n"%conf
|
+ "Status: %d confirmations\n"%conf
|
||||||
if is_mine:
|
if is_mine:
|
||||||
if fee:
|
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)
|
+ "Transaction fee: %s\n"% format_satoshis(fee, False)
|
||||||
else:
|
else:
|
||||||
tx_details += "Amount sent: %s\n"% format_satoshis(v, False) \
|
tx_details += "Amount sent: %s\n"% format_satoshis(v, False) \
|
||||||
@@ -554,6 +558,7 @@ class Wallet:
|
|||||||
h = self.history.get(addr, [])
|
h = self.history.get(addr, [])
|
||||||
if h == ['*']: continue
|
if h == ['*']: continue
|
||||||
for tx_hash, tx_height in h:
|
for tx_hash, tx_height in h:
|
||||||
|
tx = self.transactions.get(tx_hash)
|
||||||
for output in tx.get('outputs'):
|
for output in tx.get('outputs'):
|
||||||
if output.get('address') != addr: continue
|
if output.get('address') != addr: continue
|
||||||
key = tx_hash + ":%d" % output.get('index')
|
key = tx_hash + ":%d" % output.get('index')
|
||||||
@@ -654,9 +659,8 @@ class Wallet:
|
|||||||
|
|
||||||
def receive_history_callback(self, addr, hist):
|
def receive_history_callback(self, addr, hist):
|
||||||
|
|
||||||
if hist != ['*']:
|
if not self.check_new_history(addr, hist):
|
||||||
if not self.check_new_history(addr, hist):
|
raise BaseException("error: received history for %s is not consistent with known transactions"%addr)
|
||||||
raise BaseException("error: received history for %s is not consistent with known transactions"%addr)
|
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.history[addr] = hist
|
self.history[addr] = hist
|
||||||
@@ -696,12 +700,9 @@ class Wallet:
|
|||||||
tx_hash = tx['tx_hash']
|
tx_hash = tx['tx_hash']
|
||||||
timestamp = tx.get('timestamp')
|
timestamp = tx.get('timestamp')
|
||||||
conf = self.verifier.get_confirmations(tx_hash) if self.verifier else None
|
conf = self.verifier.get_confirmations(tx_hash) if self.verifier else None
|
||||||
is_mine, v, fee = self.get_tx_value(tx_hash)
|
is_mine, value, fee = self.get_tx_value(tx_hash)
|
||||||
if v is not None:
|
if value is not None:
|
||||||
balance += v
|
balance += value
|
||||||
value = v + fee if fee is not None else v
|
|
||||||
else:
|
|
||||||
value = None
|
|
||||||
|
|
||||||
result.append( (tx_hash, conf, is_mine, value, fee, balance, timestamp) )
|
result.append( (tx_hash, conf, is_mine, value, fee, balance, timestamp) )
|
||||||
|
|
||||||
@@ -1068,15 +1069,58 @@ class Wallet:
|
|||||||
|
|
||||||
|
|
||||||
def check_new_history(self, addr, hist):
|
def check_new_history(self, addr, hist):
|
||||||
# - check that all tx in hist are relevant
|
|
||||||
for tx_hash, height in hist:
|
# check that all tx in hist are relevant
|
||||||
tx = self.transactions.get(tx_hash)
|
if hist != ['*']:
|
||||||
if not tx: continue
|
for tx_hash, height in hist:
|
||||||
if not self.is_addr_in_tx(addr,tx):
|
tx = self.transactions.get(tx_hash)
|
||||||
return False
|
if not tx: continue
|
||||||
|
if not self.is_addr_in_tx(addr,tx):
|
||||||
|
return False
|
||||||
|
|
||||||
# todo: check that we are not "orphaning" a transaction
|
# check that we are not "orphaning" a transaction
|
||||||
# if we are, reject tx if unconfirmed, else reject the server
|
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
|
return True
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user