electrum

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

commit c6c8c5c077d0799176b038fefb291fe4690fed27
parent 6f5180ded00af59b1ece9fa6b9fdeabd280d016e
Author: ThomasV <thomasv@gitorious>
Date:   Thu, 15 Mar 2012 00:18:07 +0300

Merge branch 'master' of gitorious.org:electrum/electrum

Diffstat:
Mclient/electrum | 2+-
Mclient/gui.py | 32++++++++++++++++----------------
Mclient/gui_qt.py | 25+++++++++++++------------
Mclient/interface.py | 95++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mclient/wallet.py | 11++++++-----
5 files changed, 87 insertions(+), 78 deletions(-)

diff --git a/client/electrum b/client/electrum @@ -163,7 +163,7 @@ if __name__ == '__main__': cmd = 'help' # open session - if cmd not in ['password', 'mktx', 'history', 'label', 'contacts', 'help', 'validateaddress', 'signmessage', 'verifymessage', 'eval', 'create']: + if cmd not in ['password', 'mktx', 'history', 'label', 'contacts', 'help', 'validateaddress', 'signmessage', 'verifymessage', 'eval', 'create', 'addresses']: interface.start_session(wallet) interface.update_wallet(wallet) wallet.save() diff --git a/client/gui.py b/client/gui.py @@ -265,18 +265,18 @@ def run_settings_dialog(wallet, parent): def run_network_dialog( wallet, parent ): image = gtk.Image() image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_DIALOG) - + interface = wallet.interface if parent: - if wallet.interface.is_connected: - status = "Connected to %s.\n%d blocks\nresponse time: %f"%(wallet.interface.host, wallet.interface.blocks, wallet.interface.rtime) + if interface.is_connected: + status = "Connected to %s:%d\n%d blocks\nresponse time: %f"%(interface.host, interface.port, interface.blocks, interface.rtime) else: status = "Not connected" - host = wallet.interface.host - port = wallet.interface.port + host = wallet.host + port = wallet.port else: import random status = "Please choose a server." - host = random.choice( wallet.interface.servers ) + host = random.choice( interface.servers ) port = 50000 dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, @@ -1031,37 +1031,37 @@ class ElectrumWindow: return vbox def update_status_bar(self): - + interface = self.wallet.interface if self.funds_error: text = "Not enough funds" - elif self.wallet.interface.is_connected: - self.network_button.set_tooltip_text("Connected to %s.\n%d blocks\nresponse time: %f"%(self.wallet.interface.host, self.wallet.interface.blocks, self.wallet.interface.rtime)) - if self.wallet.interface.blocks == 0: + elif interface.is_connected: + self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks\nresponse time: %f"%(interface.host, interface.port, interface.blocks, interface.rtime)) + if interface.blocks == 0: self.status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU) text = "Server not ready" - elif not self.wallet.interface.is_up_to_date: + elif not interface.is_up_to_date: self.status_image.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) text = "Synchronizing..." else: self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) - self.network_button.set_tooltip_text("Connected to %s.\n%d blocks\nresponse time: %f"%(self.wallet.interface.host, self.wallet.interface.blocks, self.wallet.interface.rtime)) + self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks\nresponse time: %f"%(interface.host, interface.port, interface.blocks, interface.rtime)) c, u = self.wallet.get_balance() text = "Balance: %s "%( format_satoshis(c) ) if u: text += "[%s unconfirmed]"%( format_satoshis(u,True) ) else: self.status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU) - self.network_button.set_tooltip_text("Trying to contact %s.\n%d blocks"%(self.wallet.interface.host, self.wallet.interface.blocks)) + self.network_button.set_tooltip_text("Trying to contact %s.\n%d blocks"%(interface.host, interface.blocks)) text = "Not connected" self.status_bar.pop(self.context_id) self.status_bar.push(self.context_id, text) - if self.wallet.interface.was_updated: + if interface.was_updated: self.update_history_tab() self.update_receiving_tab() # addressbook too... - self.info.set_text( self.wallet.interface.message ) - self.wallet.interface.was_updated = False + self.info.set_text( interface.message ) + interface.was_updated = False def update_receiving_tab(self): diff --git a/client/gui_qt.py b/client/gui_qt.py @@ -208,7 +208,7 @@ class ElectrumWindow(QMainWindow): self.statusBar().showMessage(text) self.status_button.setIcon( icon ) - if self.wallet.interface.was_updated: + if self.wallet.interface.was_updated and self.wallet.interface.is_up_to_date: self.wallet.interface.was_updated = False self.textbox.setText( self.wallet.interface.message ) self.update_history_tab() @@ -787,7 +787,8 @@ class ElectrumWindow(QMainWindow): show_message("no seed") sys.exit(1) - wallet.seed = seed + wallet.seed = str(seed) + #print repr(wallet.seed) wallet.gap_limit = gap return True @@ -828,19 +829,19 @@ class ElectrumWindow(QMainWindow): @staticmethod def network_dialog(wallet, parent=None): - + interface = wallet.interface if parent: - if wallet.interface.is_connected: - status = "Connected to %s.\n%d blocks\nresponse time: %f"%(wallet.interface.host, wallet.interface.blocks, wallet.interface.rtime) + if interface.is_connected: + status = "Connected to %s:%d\n%d blocks\nresponse time: %f"%(interface.host, interface.port, interface.blocks, interface.rtime) else: status = "Not connected" - host = wallet.interface.host - port = wallet.interface.port + host = wallet.host + port = wallet.port else: import random status = "Please choose a server." - host = random.choice( wallet.interface.servers ) - port = 50000 + host = random.choice( interface.servers ) + port = wallet.default_port d = QDialog(parent) d.setModal(1) @@ -869,7 +870,7 @@ class ElectrumWindow(QMainWindow): servers_list.setMaximumHeight(150) for item in wallet.interface.servers: servers_list.addTopLevelItem(QTreeWidgetItem( [ item ] )) - servers_list.connect(servers_list, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x:host_line.setText( x.text(0) + ':50000' )) + servers_list.connect(servers_list, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x:host_line.setText( x.text(0) + ':%d'%wallet.default_port )) vbox.addWidget(servers_list) vbox.addLayout(ok_cancel_buttons(d)) @@ -884,7 +885,7 @@ class ElectrumWindow(QMainWindow): port = int(port) else: host = hh - port = 50000 + port = wallet.default_port except: show_message("error") if parent == None: @@ -925,7 +926,7 @@ class ElectrumGui(): else: # ask for seed and gap. if not ElectrumWindow.seed_dialog( wallet ): return False - wallet.init_mpk( wallet.seed ) # not encrypted at this point + wallet.init_mpk( wallet.seed ) # not encrypted at this point wallet.synchronize() if wallet.is_found(): diff --git a/client/interface.py b/client/interface.py @@ -22,13 +22,16 @@ import random, socket, ast import thread, traceback, sys, time, json -DEFAULT_TIMEOUT=5 +DEFAULT_TIMEOUT = 5 +DEFAULT_SERVERS = ['ecdsa.org','electrum.novit.ro'] # list of default servers + class Interface: - def __init__(self): - self.default_servers = ['ecdsa.org','electrum.novit.ro'] # list of default servers - self.host = random.choice( self.default_servers ) # random choice when the wallet is created - self.servers = self.default_servers # actual list from IRC + def __init__(self, host, port): + self.host = host + self.port = port + + self.servers = DEFAULT_SERVERS # actual list from IRC self.rtime = 0 self.blocks = 0 self.message = '' @@ -58,10 +61,8 @@ class Interface: class NativeInterface(Interface): """This is the original Electrum protocol. It uses polling, and a non-persistent tcp connection""" - def __init__(self, host=None, port=50000): - Interface.__init__(self) - if host: self.host = host - self.port = port + def __init__(self, host, port): + Interface.__init__(self, host, port) def start_session(self, wallet): addresses = wallet.all_addresses() @@ -159,7 +160,7 @@ class NativeInterface(Interface): # if my server is not reachable, I should get the list from one of the default servers # requesting servers could be an independent process while True: - for server in self.default_servers: + for server in DEFAULT_SERVERS: try: self.peers_server = server out = self.handler('peers') @@ -177,17 +178,37 @@ class NativeInterface(Interface): +class HttpInterface(NativeInterface): + + def handler(self, method, params = []): + import urllib2, json, time + if type(params) != type([]): params = [ params ] + t1 = time.time() + data = { 'method':method, 'id':'jsonrpc', 'params':params } + data_json = json.dumps(data) + host = 'http://%s:%d'%( self.host if method!='peers' else self.peers_server, self.port ) + req = urllib2.Request(host, data_json, {'content-type': 'application/json'}) + response_stream = urllib2.urlopen(req) + response = json.loads( response_stream.read() ) + out = response.get('result') + if not out: + print response + self.rtime = time.time() - t1 + self.is_connected = True + return out + + + + import threading class TCPInterface(Interface): """json-rpc over persistent TCP connection""" - def __init__(self, host=None, port=50001): - Interface.__init__(self) - if host: self.host = host - self.port = 50001 + def __init__(self, host, port): + Interface.__init__(self, host, port) + self.tx_event = threading.Event() - self.addresses_waiting_for_status = [] self.addresses_waiting_for_history = [] # up to date @@ -300,41 +321,25 @@ class TCPInterface(Interface): -class HttpInterface(Interface): - - def __init__(self): - self.port = 8081 - - def handler(self, method, params = []): - import urllib2, json, time - if type(params) != type([]): params = [ params ] - t1 = time.time() - data = { 'method':method, 'id':'jsonrpc', 'params':params } - data_json = json.dumps(data) - host = 'http://%s:%d'%( self.host if cmd!='peers' else self.peers_server, self.port ) - req = urllib2.Request(host, data_json, {'content-type': 'application/json'}) - response_stream = urllib2.urlopen(req) - response = json.loads( response_stream.read() ) - out = response.get('result') - if not out: - print response - self.rtime = time.time() - t1 - self.is_connected = True - return out - def new_interface(wallet): - host = wallet.host + if wallet.host: + host = wallet.host + else: + host = random.choice( DEFAULT_SERVERS ) # random choice when the wallet is created port = wallet.port + if port == 50000: interface = NativeInterface(host,port) elif port == 50001: interface = TCPInterface(host,port) - elif port in [80,8080,81,8181]: + elif port in [80, 81, 8080, 8081]: interface = HttpInterface(host,port) else: - raise BaseException("unknown protocol: %d"%port) + print "unknown port number: %d. using native protocol."%port + interface = NativeInterface(host,port) + return interface @@ -343,14 +348,16 @@ def loop_interfaces_thread(wallet): try: wallet.interface.start_session(wallet) wallet.interface.get_servers() + + wallet.interface.disconnected_event.wait() + print "Disconnected" except socket.error: - print "Not connected" + print "socket error" time.sleep(5) - continue except: traceback.print_exc(file=sys.stdout) continue - wallet.interface.disconnected_event.wait() - print "Disconnected" + + print "Starting new session: %s:%d"%(wallet.host,wallet.port) wallet.interface = new_interface(wallet) diff --git a/client/wallet.py b/client/wallet.py @@ -263,6 +263,7 @@ class Wallet: self.imported_keys = {} self.remote_url = None + self.default_port = 50001 def set_server(self, host, port): @@ -529,9 +530,9 @@ class Wallet: 'use_encryption':self.use_encryption, 'master_public_key': self.master_public_key.encode('hex'), 'fee':self.fee, - 'host':self.interface.host, - 'port':self.interface.port, - 'blocks':self.interface.blocks, + 'host':self.host, + 'port':self.port, + #'blocks':self.interface.blocks, 'seed':self.seed, 'addresses':self.addresses, 'change_addresses':self.change_addresses, @@ -558,8 +559,8 @@ class Wallet: data = f.read() f.close() except: - #self.interface = NativeInterface() - self.port = 50000 + self.host = '' + self.port = self.default_port return try: d = ast.literal_eval( data )