fix recovery procedure
This commit is contained in:
parent
d0dd8c847a
commit
81bb04378f
|
@ -839,15 +839,11 @@ class ElectrumWindow(QMainWindow):
|
||||||
status = "Connected to %s:%d\n%d blocks\nresponse time: %f"%(interface.host, interface.port, wallet.blocks, interface.rtime)
|
status = "Connected to %s:%d\n%d blocks\nresponse time: %f"%(interface.host, interface.port, wallet.blocks, interface.rtime)
|
||||||
else:
|
else:
|
||||||
status = "Not connected"
|
status = "Not connected"
|
||||||
host = wallet.host
|
server = wallet.server
|
||||||
port = wallet.port
|
|
||||||
protocol = wallet.protocol
|
|
||||||
else:
|
else:
|
||||||
import random
|
import random
|
||||||
status = "Please choose a server."
|
status = "Please choose a server."
|
||||||
host = random.choice( interface.servers )
|
server = random.choice( interface.servers )
|
||||||
port = wallet.port
|
|
||||||
protocol = 's'
|
|
||||||
|
|
||||||
d = QDialog(parent)
|
d = QDialog(parent)
|
||||||
d.setModal(1)
|
d.setModal(1)
|
||||||
|
@ -867,7 +863,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
|
|
||||||
hbox = QHBoxLayout()
|
hbox = QHBoxLayout()
|
||||||
host_line = QLineEdit()
|
host_line = QLineEdit()
|
||||||
host_line.setText("%s:%d:%s"% (host,port,protocol) )
|
host_line.setText(server)
|
||||||
hbox.addWidget(QLabel('Connect to:'))
|
hbox.addWidget(QLabel('Connect to:'))
|
||||||
hbox.addWidget(host_line)
|
hbox.addWidget(host_line)
|
||||||
vbox.addLayout(hbox)
|
vbox.addLayout(hbox)
|
||||||
|
@ -877,7 +873,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
servers_list.setHeaderLabels( [ 'Active servers'] )
|
servers_list.setHeaderLabels( [ 'Active servers'] )
|
||||||
servers_list.setMaximumHeight(150)
|
servers_list.setMaximumHeight(150)
|
||||||
for item in wallet.interface.servers:
|
for item in wallet.interface.servers:
|
||||||
servers_list.addTopLevelItem(QTreeWidgetItem( [ item[1] + ':' + item[0] ] ))
|
servers_list.addTopLevelItem(QTreeWidgetItem( [ item ] ))
|
||||||
servers_list.connect(servers_list, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x:host_line.setText( x.text(0) ))
|
servers_list.connect(servers_list, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x:host_line.setText( x.text(0) ))
|
||||||
vbox.addWidget(servers_list)
|
vbox.addWidget(servers_list)
|
||||||
else:
|
else:
|
||||||
|
@ -891,16 +887,11 @@ class ElectrumWindow(QMainWindow):
|
||||||
d.setLayout(vbox)
|
d.setLayout(vbox)
|
||||||
|
|
||||||
if not d.exec_(): return
|
if not d.exec_(): return
|
||||||
hh = unicode( host_line.text() )
|
server = unicode( host_line.text() )
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if ':' in hh:
|
a,b,c = server.split(':')
|
||||||
host, port, protocol = hh.split(':')
|
b = int(b)
|
||||||
port = int(port)
|
|
||||||
else:
|
|
||||||
host = hh
|
|
||||||
port = wallet.port
|
|
||||||
protocol = wallet.protocol
|
|
||||||
except:
|
except:
|
||||||
QMessageBox.information(None, 'Error', 'error', 'OK')
|
QMessageBox.information(None, 'Error', 'error', 'OK')
|
||||||
if parent == None:
|
if parent == None:
|
||||||
|
@ -908,7 +899,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
wallet.set_server(host, port, protocol)
|
wallet.set_server(server)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,20 +42,15 @@ class Interface:
|
||||||
self.rtime = 0
|
self.rtime = 0
|
||||||
|
|
||||||
self.is_connected = True
|
self.is_connected = True
|
||||||
|
self.poll_interval = 1
|
||||||
#only asynchrnous
|
|
||||||
self.addresses_waiting_for_status = []
|
|
||||||
self.addresses_waiting_for_history = []
|
|
||||||
|
|
||||||
#json
|
#json
|
||||||
self.message_id = 0
|
self.message_id = 0
|
||||||
self.responses = Queue.Queue()
|
self.responses = Queue.Queue()
|
||||||
|
|
||||||
|
def poke(self):
|
||||||
def is_up_to_date(self):
|
# push a fake response so that the getting thread exits its loop
|
||||||
return self.responses.empty() and not ( self.addresses_waiting_for_status or self.addresses_waiting_for_history )
|
self.responses.put(None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def queue_json_response(self, c):
|
def queue_json_response(self, c):
|
||||||
#print repr(c)
|
#print repr(c)
|
||||||
|
@ -70,26 +65,13 @@ class Interface:
|
||||||
if error:
|
if error:
|
||||||
print "received error:", c, method, params
|
print "received error:", c, method, params
|
||||||
else:
|
else:
|
||||||
self.update_waiting_lists(method, params)
|
|
||||||
self.responses.put({'method':method, 'params':params, 'result':result})
|
self.responses.put({'method':method, 'params':params, 'result':result})
|
||||||
|
|
||||||
|
|
||||||
def update_waiting_lists(self, method, params):
|
|
||||||
if method == 'blockchain.address.subscribe':
|
|
||||||
addr = params[-1]
|
|
||||||
if addr in self.addresses_waiting_for_status:
|
|
||||||
self.addresses_waiting_for_status.remove(addr)
|
|
||||||
elif method == 'blockchain.address.get_history':
|
|
||||||
addr = params[0]
|
|
||||||
if addr in self.addresses_waiting_for_history:
|
|
||||||
self.addresses_waiting_for_history.remove(addr)
|
|
||||||
|
|
||||||
|
|
||||||
def subscribe(self, addresses):
|
def subscribe(self, addresses):
|
||||||
messages = []
|
messages = []
|
||||||
for addr in addresses:
|
for addr in addresses:
|
||||||
messages.append(('blockchain.address.subscribe', [addr]))
|
messages.append(('blockchain.address.subscribe', [addr]))
|
||||||
self.addresses_waiting_for_status.append(addr)
|
|
||||||
self.send(messages)
|
self.send(messages)
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,11 +122,11 @@ class PollingInterface(Interface):
|
||||||
#else:
|
#else:
|
||||||
# return False
|
# return False
|
||||||
|
|
||||||
def poll_thread(self, poll_interval):
|
def poll_thread(self):
|
||||||
while self.is_connected:
|
while self.is_connected:
|
||||||
try:
|
try:
|
||||||
self.poll()
|
self.poll()
|
||||||
time.sleep(poll_interval)
|
time.sleep(self.poll_interval)
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
break
|
break
|
||||||
except socket.error:
|
except socket.error:
|
||||||
|
@ -166,7 +148,7 @@ class NativeInterface(PollingInterface):
|
||||||
def start_session(self, addresses, version):
|
def start_session(self, addresses, version):
|
||||||
self.send([('session.new', [ version, addresses ])] )
|
self.send([('session.new', [ version, addresses ])] )
|
||||||
self.send([('server.peers.subscribe',[])])
|
self.send([('server.peers.subscribe',[])])
|
||||||
thread.start_new_thread(self.poll_thread, (5,))
|
thread.start_new_thread(self.poll_thread, ())
|
||||||
|
|
||||||
def send(self, messages):
|
def send(self, messages):
|
||||||
import time
|
import time
|
||||||
|
@ -186,7 +168,7 @@ class NativeInterface(PollingInterface):
|
||||||
params = self.session_id
|
params = self.session_id
|
||||||
|
|
||||||
if cmd == 'address.subscribe':
|
if cmd == 'address.subscribe':
|
||||||
params = [ self.session_id] + params
|
params = [ self.session_id ] + params
|
||||||
|
|
||||||
if cmd in ['h', 'tx']:
|
if cmd in ['h', 'tx']:
|
||||||
str_params = params[0]
|
str_params = params[0]
|
||||||
|
@ -212,16 +194,16 @@ class NativeInterface(PollingInterface):
|
||||||
if cmd == 'h':
|
if cmd == 'h':
|
||||||
out = old_to_new(out)
|
out = old_to_new(out)
|
||||||
|
|
||||||
if cmd in[ 'peers','h','poll']:
|
if cmd in ['peers','h','poll']:
|
||||||
out = ast.literal_eval( out )
|
out = ast.literal_eval( out )
|
||||||
|
|
||||||
if out=='': out=None #fixme
|
if out == '':
|
||||||
|
out = None
|
||||||
|
|
||||||
if cmd == 'new_session':
|
if cmd == 'new_session':
|
||||||
self.session_id, msg = ast.literal_eval( out )
|
self.session_id, msg = ast.literal_eval( out )
|
||||||
self.responses.put({'method':'server.banner', 'params':[], 'result':msg})
|
self.responses.put({'method':'server.banner', 'params':[], 'result':msg})
|
||||||
else:
|
else:
|
||||||
self.update_waiting_lists(method, params)
|
|
||||||
self.responses.put({'method':method, 'params':params, 'result':out})
|
self.responses.put({'method':method, 'params':params, 'result':out})
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,7 +213,7 @@ class HttpInterface(PollingInterface):
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.session_id = None
|
self.session_id = None
|
||||||
thread.start_new_thread(self.poll_thread, (15,))
|
thread.start_new_thread(self.poll_thread, ())
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
if self.session_id:
|
if self.session_id:
|
||||||
|
@ -280,6 +262,13 @@ class HttpInterface(PollingInterface):
|
||||||
for item in response:
|
for item in response:
|
||||||
self.queue_json_response(item)
|
self.queue_json_response(item)
|
||||||
|
|
||||||
|
if response:
|
||||||
|
self.poll_interval = 1
|
||||||
|
else:
|
||||||
|
if self.poll_interval < 15:
|
||||||
|
self.poll_interval += 1
|
||||||
|
#print self.poll_interval, response
|
||||||
|
|
||||||
self.rtime = time.time() - t1
|
self.rtime = time.time() - t1
|
||||||
self.is_connected = True
|
self.is_connected = True
|
||||||
|
|
||||||
|
@ -313,8 +302,7 @@ class AsynchronousInterface(Interface):
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
|
|
||||||
self.is_connected = False
|
self.is_connected = False
|
||||||
# push None so that the getting thread exits its loop
|
self.poke()
|
||||||
self.responses.put(None)
|
|
||||||
|
|
||||||
def send(self, messages):
|
def send(self, messages):
|
||||||
out = ''
|
out = ''
|
||||||
|
@ -327,7 +315,6 @@ class AsynchronousInterface(Interface):
|
||||||
|
|
||||||
def get_history(self, addr):
|
def get_history(self, addr):
|
||||||
self.send([('blockchain.address.get_history', [addr])])
|
self.send([('blockchain.address.get_history', [addr])])
|
||||||
self.addresses_waiting_for_history.append(addr)
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
|
self.s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
|
||||||
|
|
|
@ -251,7 +251,6 @@ class Wallet:
|
||||||
self.addresses = [] # receiving addresses visible for user
|
self.addresses = [] # receiving addresses visible for user
|
||||||
self.change_addresses = [] # addresses used as change
|
self.change_addresses = [] # addresses used as change
|
||||||
self.seed = '' # encrypted
|
self.seed = '' # encrypted
|
||||||
self.status = {} # current status of addresses
|
|
||||||
self.history = {}
|
self.history = {}
|
||||||
self.labels = {} # labels for addresses and transactions
|
self.labels = {} # labels for addresses and transactions
|
||||||
self.aliases = {} # aliases for addresses
|
self.aliases = {} # aliases for addresses
|
||||||
|
@ -261,9 +260,7 @@ class Wallet:
|
||||||
self.receipt = None # next receipt
|
self.receipt = None # next receipt
|
||||||
self.addressbook = [] # outgoing addresses, for payments
|
self.addressbook = [] # outgoing addresses, for payments
|
||||||
|
|
||||||
self.host = random.choice( DEFAULT_SERVERS ) # random choice when the wallet is created
|
self.server = random.choice( DEFAULT_SERVERS ) + ':50000:n' # random choice when the wallet is created
|
||||||
self.port = DEFAULT_PORT
|
|
||||||
self.protocol = 'n'
|
|
||||||
|
|
||||||
# not saved
|
# not saved
|
||||||
self.tx_history = {}
|
self.tx_history = {}
|
||||||
|
@ -280,12 +277,18 @@ class Wallet:
|
||||||
self.interface_lock = threading.Lock()
|
self.interface_lock = threading.Lock()
|
||||||
self.tx_event = threading.Event()
|
self.tx_event = threading.Event()
|
||||||
|
|
||||||
|
#
|
||||||
|
self.addresses_waiting_for_status = []
|
||||||
|
self.addresses_waiting_for_history = []
|
||||||
|
|
||||||
def set_server(self, host, port, protocol):
|
|
||||||
if host!= self.host or port!=self.port or protocol!=self.protocol:
|
def is_up_to_date(self):
|
||||||
self.host = host
|
return self.interface.responses.empty() and not ( self.addresses_waiting_for_status or self.addresses_waiting_for_history )
|
||||||
self.port = port
|
|
||||||
self.protocol = protocol
|
|
||||||
|
def set_server(self, server):
|
||||||
|
if server != self.server:
|
||||||
|
self.server = server
|
||||||
self.interface.is_connected = False # this exits the polling loop
|
self.interface.is_connected = False # this exits the polling loop
|
||||||
|
|
||||||
def set_path(self, wallet_path):
|
def set_path(self, wallet_path):
|
||||||
|
@ -460,7 +463,6 @@ class Wallet:
|
||||||
self.addresses.append(address)
|
self.addresses.append(address)
|
||||||
|
|
||||||
self.history[address] = []
|
self.history[address] = []
|
||||||
self.status[address] = None
|
|
||||||
print address
|
print address
|
||||||
return address
|
return address
|
||||||
|
|
||||||
|
@ -530,13 +532,10 @@ class Wallet:
|
||||||
'use_encryption':self.use_encryption,
|
'use_encryption':self.use_encryption,
|
||||||
'master_public_key': self.master_public_key.encode('hex'),
|
'master_public_key': self.master_public_key.encode('hex'),
|
||||||
'fee':self.fee,
|
'fee':self.fee,
|
||||||
'host':self.host,
|
'server':self.server,
|
||||||
'port':self.port,
|
|
||||||
'protocol':self.protocol,
|
|
||||||
'seed':self.seed,
|
'seed':self.seed,
|
||||||
'addresses':self.addresses,
|
'addresses':self.addresses,
|
||||||
'change_addresses':self.change_addresses,
|
'change_addresses':self.change_addresses,
|
||||||
'status':self.status,
|
|
||||||
'history':self.history,
|
'history':self.history,
|
||||||
'labels':self.labels,
|
'labels':self.labels,
|
||||||
'contacts':self.addressbook,
|
'contacts':self.addressbook,
|
||||||
|
@ -568,13 +567,10 @@ class Wallet:
|
||||||
self.use_encryption = d.get('use_encryption')
|
self.use_encryption = d.get('use_encryption')
|
||||||
self.fee = int( d.get('fee') )
|
self.fee = int( d.get('fee') )
|
||||||
self.seed = d.get('seed')
|
self.seed = d.get('seed')
|
||||||
self.host = d.get('host')
|
self.server = d.get('server')
|
||||||
self.protocol = d.get('protocol','n')
|
|
||||||
self.port = d.get('port')
|
|
||||||
blocks = d.get('blocks')
|
blocks = d.get('blocks')
|
||||||
self.addresses = d.get('addresses')
|
self.addresses = d.get('addresses')
|
||||||
self.change_addresses = d.get('change_addresses')
|
self.change_addresses = d.get('change_addresses')
|
||||||
self.status = d.get('status')
|
|
||||||
self.history = d.get('history')
|
self.history = d.get('history')
|
||||||
self.labels = d.get('labels')
|
self.labels = d.get('labels')
|
||||||
self.addressbook = d.get('contacts')
|
self.addressbook = d.get('contacts')
|
||||||
|
@ -692,17 +688,30 @@ class Wallet:
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def get_status(self, address):
|
||||||
|
h = self.history.get(address)
|
||||||
|
if not h:
|
||||||
|
status = None
|
||||||
|
else:
|
||||||
|
lastpoint = h[-1]
|
||||||
|
status = lastpoint['block_hash']
|
||||||
|
if status == 'mempool':
|
||||||
|
status = status + ':%d'% len(h)
|
||||||
|
return status
|
||||||
|
|
||||||
def receive_status_callback(self, addr, status):
|
def receive_status_callback(self, addr, status):
|
||||||
if self.status.get(addr) != status:
|
if self.get_status(addr) != status:
|
||||||
#print "updating status for", addr, repr(self.status.get(addr)), repr(status)
|
#print "updating status for", addr, status
|
||||||
self.status[addr] = status
|
self.addresses_waiting_for_history.append(addr)
|
||||||
self.interface.get_history(addr)
|
self.interface.get_history(addr)
|
||||||
|
if addr in self.addresses_waiting_for_status: self.addresses_waiting_for_status.remove(addr)
|
||||||
|
|
||||||
def receive_history_callback(self, addr, data):
|
def receive_history_callback(self, addr, data):
|
||||||
#print "updating history for", addr
|
#print "updating history for", addr
|
||||||
self.history[addr] = data
|
self.history[addr] = data
|
||||||
self.update_tx_history()
|
self.update_tx_history()
|
||||||
self.save()
|
self.save()
|
||||||
|
if addr in self.addresses_waiting_for_history: self.addresses_waiting_for_history.remove(addr)
|
||||||
|
|
||||||
def get_tx_history(self):
|
def get_tx_history(self):
|
||||||
lines = self.tx_history.values()
|
lines = self.tx_history.values()
|
||||||
|
@ -948,11 +957,11 @@ class Wallet:
|
||||||
if len(item)>2:
|
if len(item)>2:
|
||||||
for v in item[2]:
|
for v in item[2]:
|
||||||
if re.match("[nsh]\d+",v):
|
if re.match("[nsh]\d+",v):
|
||||||
s.append((v[0],host+":"+v[1:]))
|
s.append(host+":"+v[1:]+":"+v[0])
|
||||||
if not s:
|
if not s:
|
||||||
s.append(("n",host+":50000"))
|
s.append(host+":50000:n")
|
||||||
else:
|
else:
|
||||||
s.append(("n",host+":50000"))
|
s.append(host+":50000:n")
|
||||||
servers = servers + s
|
servers = servers + s
|
||||||
self.interface.servers = servers
|
self.interface.servers = servers
|
||||||
|
|
||||||
|
@ -980,6 +989,7 @@ class Wallet:
|
||||||
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
self.interface.poke()
|
||||||
self.up_to_date_event.wait()
|
self.up_to_date_event.wait()
|
||||||
|
|
||||||
|
|
||||||
|
@ -988,7 +998,10 @@ class Wallet:
|
||||||
new_addresses = self.synchronize()
|
new_addresses = self.synchronize()
|
||||||
if new_addresses:
|
if new_addresses:
|
||||||
self.interface.subscribe(new_addresses)
|
self.interface.subscribe(new_addresses)
|
||||||
if self.interface.is_up_to_date() and not new_addresses:
|
for addr in new_addresses:
|
||||||
|
self.addresses_waiting_for_status.append(addr)
|
||||||
|
|
||||||
|
if self.is_up_to_date():
|
||||||
self.up_to_date = True
|
self.up_to_date = True
|
||||||
self.up_to_date_event.set()
|
self.up_to_date_event.set()
|
||||||
else:
|
else:
|
||||||
|
@ -999,19 +1012,25 @@ class Wallet:
|
||||||
|
|
||||||
|
|
||||||
def start_interface(self):
|
def start_interface(self):
|
||||||
if self.protocol == 'n':
|
|
||||||
|
host, port, protocol = self.server.split(':')
|
||||||
|
port = int(port)
|
||||||
|
|
||||||
|
if protocol == 'n':
|
||||||
InterfaceClass = NativeInterface
|
InterfaceClass = NativeInterface
|
||||||
elif self.protocol == 's':
|
elif protocol == 's':
|
||||||
InterfaceClass = AsynchronousInterface
|
InterfaceClass = AsynchronousInterface
|
||||||
elif self.protocol == 'h':
|
elif protocol == 'h':
|
||||||
InterfaceClass = HttpInterface
|
InterfaceClass = HttpInterface
|
||||||
else:
|
else:
|
||||||
print "unknown protocol"
|
print "unknown protocol"
|
||||||
InterfaceClass = NativeInterface
|
InterfaceClass = NativeInterface
|
||||||
|
|
||||||
self.interface = InterfaceClass(self.host, self.port)
|
self.interface = InterfaceClass(host, port)
|
||||||
addresses = self.all_addresses()
|
addresses = self.all_addresses()
|
||||||
version = self.electrum_version
|
version = self.electrum_version
|
||||||
|
for addr in addresses:
|
||||||
|
self.addresses_waiting_for_status.append(addr)
|
||||||
self.interface.start_session(addresses,version)
|
self.interface.start_session(addresses,version)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue