replace wallet.interface everywhere
authorthomasv <thomasv@gitorious>
Thu, 12 Sep 2013 12:58:42 +0000 (14:58 +0200)
committerthomasv <thomasv@gitorious>
Thu, 12 Sep 2013 12:58:42 +0000 (14:58 +0200)
gui/gui_classic/installwizard.py
gui/gui_classic/lite_window.py
gui/gui_classic/main_window.py
gui/gui_classic/network_dialog.py
gui/gui_gtk.py
gui/gui_text.py
lib/blockchain.py
lib/interface.py
lib/network.py
lib/wallet.py

index a83d06b..a7454a2 100644 (file)
@@ -242,17 +242,16 @@ class InstallWizard(QDialog):
     def restore_wallet(self, wallet):
 
         # wait until we are connected, because the user might have selected another server
-        if not wallet.interface.is_connected:
-            waiting = lambda: False if wallet.interface.is_connected else "%s \n" % (_("Connecting..."))
+        if not self.network.interface.is_connected:
+            waiting = lambda: False if self.network.interface.is_connected else "%s \n" % (_("Connecting..."))
             waiting_dialog(waiting)
 
         waiting = lambda: False if wallet.is_up_to_date() else "%s\n%s %d\n%s %.1f"\
-            %(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), wallet.interface.bytes_received/1024.)
+            %(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), self.network.interface.bytes_received/1024.)
 
         # try to restore old account
         wallet.create_old_account()
         wallet.set_up_to_date(False)
-        wallet.interface.poke('synchronizer')
         waiting_dialog(waiting)
 
         if wallet.is_found():
@@ -262,7 +261,6 @@ class InstallWizard(QDialog):
             wallet.accounts.pop(0)
             wallet.create_accounts()
             wallet.set_up_to_date(False)
-            wallet.interface.poke('synchronizer')
             waiting_dialog(waiting)
 
         if wallet.is_found():
index b6cdd94..0b5c054 100644 (file)
@@ -832,6 +832,7 @@ class MiniDriver(QObject):
         super(QObject, self).__init__()
 
         self.wallet = wallet
+        self.network = wallet.network
         self.window = window
 
         self.wallet.network.register_callback('updated',self.update_callback)
@@ -851,9 +852,9 @@ class MiniDriver(QObject):
         self.emit(SIGNAL("updatesignal()"))
 
     def update(self):
-        if not self.wallet.interface:
+        if not self.network.interface:
             self.initializing()
-        elif not self.wallet.interface.is_connected:
+        elif not self.network.interface.is_connected:
             self.connecting()
         elif not self.wallet.up_to_date:
             self.synchronizing()
index 920d9c0..003cecc 100644 (file)
@@ -281,13 +281,11 @@ class ElectrumWindow(QMainWindow):
             self.show_message("file not found "+ filename)
             return
 
-        interface = self.wallet.interface
-        blockchain = self.wallet.verifier.blockchain
         self.wallet.stop_threads()
         
         # create new wallet 
         wallet = Wallet(storage)
-        wallet.start_threads(interface, blockchain)
+        wallet.start_threads(network)
 
         self.load_wallet(wallet)
 
@@ -302,7 +300,7 @@ class ElectrumWindow(QMainWindow):
         storage = WalletStorage({'wallet_path': filename})
         assert not storage.file_exists
 
-        wizard = installwizard.InstallWizard(self.config, self.wallet.interface, self.wallet.verifier.blockchain, storage)
+        wizard = installwizard.InstallWizard(self.config, self.network, storage)
         wallet = wizard.run()
         if wallet: 
             self.load_wallet(wallet)
@@ -410,12 +408,12 @@ class ElectrumWindow(QMainWindow):
 
     def notify_transactions(self):
         print_error("Notifying GUI")
-        if len(self.wallet.interface.pending_transactions_for_notifications) > 0:
+        if len(self.network.interface.pending_transactions_for_notifications) > 0:
             # Combine the transactions if there are more then three
-            tx_amount = len(self.wallet.interface.pending_transactions_for_notifications)
+            tx_amount = len(self.network.interface.pending_transactions_for_notifications)
             if(tx_amount >= 3):
                 total_amount = 0
-                for tx in self.wallet.interface.pending_transactions_for_notifications:
+                for tx in self.network.interface.pending_transactions_for_notifications:
                     is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx)
                     if(v > 0):
                         total_amount += v
@@ -423,11 +421,11 @@ class ElectrumWindow(QMainWindow):
                 self.notify("%s new transactions received. Total amount received in the new transactions %s %s" \
                                 % (tx_amount, self.format_amount(total_amount), self.base_unit()))
 
-                self.wallet.interface.pending_transactions_for_notifications = []
+                self.network.interface.pending_transactions_for_notifications = []
             else:
-              for tx in self.wallet.interface.pending_transactions_for_notifications:
+              for tx in self.network.interface.pending_transactions_for_notifications:
                   if tx:
-                      self.wallet.interface.pending_transactions_for_notifications.remove(tx)
+                      self.network.interface.pending_transactions_for_notifications.remove(tx)
                       is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx)
                       if(v > 0):
                           self.notify("New transaction received. %s %s" % (self.format_amount(v), self.base_unit()))
@@ -535,7 +533,7 @@ class ElectrumWindow(QMainWindow):
         return "BTC" if self.decimal_point == 8 else "mBTC"
 
     def update_status(self):
-        if self.wallet.interface and self.wallet.interface.is_connected:
+        if self.network.interface and self.network.interface.is_connected:
             if not self.wallet.up_to_date:
                 text = _("Synchronizing...")
                 icon = QIcon(":icons/status_waiting.png")
@@ -555,7 +553,7 @@ class ElectrumWindow(QMainWindow):
 
     def update_wallet(self):
         self.update_status()
-        if self.wallet.up_to_date or not self.wallet.interface.is_connected:
+        if self.wallet.up_to_date or not self.network.interface.is_connected:
             self.update_history_tab()
             self.update_receive_tab()
             self.update_contacts_tab()
@@ -1308,7 +1306,7 @@ class ElectrumWindow(QMainWindow):
         console.updateNamespace({'wallet' : self.wallet, 'network' : self.network, 'gui':self})
         console.updateNamespace({'util' : util, 'bitcoin':bitcoin})
 
-        c = commands.Commands(self.wallet, self.wallet.interface, lambda: self.console.set_json(True))
+        c = commands.Commands(self.wallet, self.network.interface, lambda: self.console.set_json(True))
         methods = {}
         def mkfunc(f, method):
             return lambda *args: apply( f, (method, args, self.password_dialog ))
index 37c57d3..47bab28 100644 (file)
@@ -239,5 +239,6 @@ class NetworkDialog(QDialog):
         self.config.set_key("proxy", proxy, True)
         self.config.set_key("server", server, True)
         self.network.set_server(server, proxy)
+
         self.config.set_key('auto_cycle', self.autocycle_cb.isChecked(), True)
         return True
index c8b1a81..635deb1 100644 (file)
@@ -33,7 +33,7 @@ import platform
 MONOSPACE_FONT = 'Lucida Console' if platform.system() == 'Windows' else 'monospace'
 
 from electrum.util import format_satoshis
-from electrum.interface import DEFAULT_SERVERS
+from electrum.network import DEFAULT_SERVERS
 from electrum.bitcoin import MIN_RELAY_TX_FEE
 
 def numbify(entry, is_int = False):
@@ -268,7 +268,7 @@ 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
+    interface = wallet.network.interface
     if parent:
         if interface.is_connected:
             status = "Connected to %s:%d\n%d blocks"%(interface.host, interface.port, wallet.network.blockchain.height)
@@ -279,7 +279,7 @@ def run_network_dialog( wallet, parent ):
         status = "Please choose a server.\nSelect cancel if you are offline."
 
     server = interface.server
-    servers = interface.get_servers()
+    servers = wallet.network.get_servers()
 
     dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                     gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, status)
@@ -345,7 +345,7 @@ def run_network_dialog( wallet, parent ):
     treeview = gtk.TreeView(model=server_list)
     treeview.show()
 
-    if wallet.interface.servers:
+    if interface.servers:
         label = 'Active Servers'
     else:
         label = 'Default Servers'
@@ -1107,7 +1107,7 @@ class ElectrumWindow:
         return vbox
 
     def update_status_bar(self):
-        interface = self.wallet.interface
+        interface = self.wallet.network.interface
         if self.funds_error:
             text = "Not enough funds"
         elif interface and interface.is_connected:
@@ -1133,7 +1133,7 @@ class ElectrumWindow:
             self.update_history_tab()
             self.update_receiving_tab()
             # addressbook too...
-            self.info.set_text( self.wallet.interface.banner )
+            self.info.set_text( self.wallet.network.banner )
             self.wallet_updated = False
 
     def update_receiving_tab(self):
index aa0bb5a..72ba085 100644 (file)
@@ -102,7 +102,7 @@ class ElectrumGui:
 
 
     def print_balance(self):
-        if self.wallet.interface and self.wallet.interface.is_connected:
+        if self.network.interface and self.network.interface.is_connected:
             if not self.wallet.up_to_date:
                 msg = _( "Synchronizing..." )
             else: 
@@ -143,7 +143,7 @@ class ElectrumGui:
         self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2))
 
     def print_banner(self):
-        for i, x in enumerate( self.wallet.interface.banner.split('\n') ):
+        for i, x in enumerate( self.network.banner.split('\n') ):
             self.stdscr.addstr( 1+i, 1, x )
 
     def print_list(self, list, firstline):
@@ -318,7 +318,7 @@ class ElectrumGui:
 
     def network_dialog(self):
         out = self.run_dialog('Network', [
-            {'label':'server', 'type':'str', 'value':self.wallet.interface.server},
+            {'label':'server', 'type':'str', 'value':self.network.interface.server},
             {'label':'proxy', 'type':'str', 'value':self.config.get('proxy', '')},
             ], buttons = 1)
         if out:
@@ -331,7 +331,7 @@ class ElectrumGui:
 
                 self.wallet.config.set_key("proxy", proxy, True)
                 self.wallet.config.set_key("server", server, True)
-                self.wallet.interface.set_server(server, proxy)
+                self.network.interface.set_server(server, proxy)
                 
 
 
index 94cc559..d0563d6 100644 (file)
@@ -65,6 +65,8 @@ class Blockchain(threading.Thread):
             if not result: continue
 
             i, result = result
+            if not result: continue
+            
             header = result.get('result')
             height = header.get('block_height')
             self.servers_height[i.server] = height
index 0dd3674..cf87442 100644 (file)
@@ -381,6 +381,12 @@ class Interface(threading.Thread):
             raise BaseException('Unknown protocol: %s'%protocol)
 
 
+    def stop_subscriptions(self):
+        for callback in self.subscriptions.keys():
+            callback(self, None)
+        self.subscriptions = {}
+
+
     def send(self, messages, callback):
 
         sub = []
@@ -430,23 +436,6 @@ class Interface(threading.Thread):
         return proxy
 
 
-    def set_server(self, server, proxy=None):
-        "todo: remove this"
-        # raise an error if the format isnt correct
-        a,b,c = server.split(':')
-        b = int(b)
-        assert c in 'stgh'
-        # set the server
-        if server != self.server or proxy != self.proxy:
-            print "changing server:", server, proxy
-            self.server = server
-            self.proxy = proxy
-            if self.is_connected and self.protocol in 'st' and self.s:
-                self.s.shutdown(socket.SHUT_RDWR)
-                self.s.close()
-            self.is_connected = False  # this exits the polling loop
-            self.trigger_callback('disconnecting') # for actively disconnecting
-
 
     def stop(self):
         if self.is_connected and self.protocol in 'st' and self.s:
index c4d8cb0..cb3f7ea 100644 (file)
@@ -45,9 +45,9 @@ class Network(threading.Thread):
         self.interfaces = {}
         self.queue = Queue.Queue()
         self.default_server = self.config.get('server')
-        self.servers_list = filter_protocol(DEFAULT_SERVERS,'s')
+        self.disconnected_servers = []
         self.callbacks = {}
-        #banner
+        self.servers = []
         self.banner = ''
 
 
@@ -66,13 +66,17 @@ class Network(threading.Thread):
 
 
     def random_server(self):
-        if len(self.servers_list) <= len(self.interfaces.keys()):
-            return
+        choice_list = []
+        l = filter_protocol(self.get_servers(), 's')
+        for s in l:
+            if s in self.disconnected_servers or s in self.interfaces.keys():
+                continue
+            else:
+                choice_list.append(s)
         
-        while True:
-            server = random.choice( self.servers_list )
-            if server not in self.interfaces.keys(): break
-
+        if not choice_list: return
+        
+        server = random.choice( choice_list )
         return server
 
 
@@ -116,11 +120,11 @@ class Network(threading.Thread):
 
 
     def set_server(self, server, proxy):
-        subscriptions = self.interface.subscriptions
+        i = self.interface
         self.default_server = server
         self.start_interface(server)
         self.interface = self.interfaces[server]
-        self.resend_subscriptions(subscriptions)
+        i.stop_subscriptions() # fixme: it should not stop all subscriptions, and send 'unsubscribe'
         self.trigger_callback('disconnecting') # for actively disconnecting
 
 
@@ -138,8 +142,9 @@ class Network(threading.Thread):
                 if i == self.interface:
                     i.send([('server.banner',[])], self.on_banner)
                     i.send([('server.peers.subscribe',[])], self.on_peers)
+                    self.trigger_callback('connected')
             else:
-                self.servers_list.remove(i.server)
+                self.disconnected_servers.append(i.server)
                 self.interfaces.pop(i.server)
                 self.start_random_interface()
                 
@@ -154,6 +159,7 @@ class Network(threading.Thread):
         self.blockchain.queue.put((i,result))
 
     def on_peers(self, i, r):
+        if not r: return
         self.servers = self.parse_servers(r.get('result'))
         self.trigger_callback('peers')
 
@@ -200,12 +206,6 @@ class Network(threading.Thread):
         return servers
 
 
-    def resend_subscriptions(self, subscriptions):
-        for channel, messages in subscriptions.items():
-            if messages:
-                self.interface.send(messages, channel)
-
-
 
 
 if __name__ == "__main__":
index 88e632b..60d38f8 100644 (file)
@@ -224,7 +224,6 @@ class Wallet:
 
     def update(self):
         self.up_to_date = False
-        #self.interface.poke('synchronizer')
         while not self.is_up_to_date(): 
             time.sleep(0.1)
 
@@ -1039,7 +1038,7 @@ class Wallet:
                 print_error("received transaction that is no longer referenced in history", tx_hash)
                 return
             self.transactions[tx_hash] = tx
-            self.interface.pending_transactions_for_notifications.append(tx)
+            self.network.interface.pending_transactions_for_notifications.append(tx)
             self.save_transactions()
             if self.verifier and tx_height>0: 
                 self.verifier.add(tx_hash, tx_height)
@@ -1188,7 +1187,7 @@ class Wallet:
     def send_tx(self, tx):
         # asynchronous
         self.tx_event.clear()
-        self.interface.send([('blockchain.transaction.broadcast', [str(tx)])], self.on_broadcast)
+        self.network.interface.send([('blockchain.transaction.broadcast', [str(tx)])], self.on_broadcast)
         return tx.hash()
 
     def on_broadcast(self, i, result):
@@ -1320,7 +1319,7 @@ class Wallet:
                     # assert not self.is_mine(_addr)
                     ext_requests.append( ('blockchain.address.get_history', [_addr]) )
 
-                ext_h = self.interface.synchronous_get(ext_requests)
+                ext_h = self.network.interface.synchronous_get(ext_requests)
                 print_error("sync:", ext_requests, ext_h)
                 height = None
                 for h in ext_h:
@@ -1362,7 +1361,6 @@ class Wallet:
     def start_threads(self, network):
         from verifier import TxVerifier
         self.network = network
-        self.interface = network.interface
         self.verifier = TxVerifier(self.network, self.storage)
         self.verifier.start()
         self.set_verifier(self.verifier)
@@ -1385,7 +1383,7 @@ class WalletSynchronizer(threading.Thread):
         self.daemon = True
         self.wallet = wallet
         wallet.synchronizer = self
-        self.interface = self.wallet.interface
+        self.network = self.wallet.network
         #self.wallet.network.register_callback('connected', lambda: self.wallet.set_up_to_date(False))
         self.was_updated = True
         self.running = False
@@ -1403,15 +1401,25 @@ class WalletSynchronizer(threading.Thread):
         messages = []
         for addr in addresses:
             messages.append(('blockchain.address.subscribe', [addr]))
-        self.interface.send( messages, lambda i,r: self.queue.put(r))
+        self.network.interface.send( messages, lambda i,r: self.queue.put(r))
 
 
     def run(self):
-        if not self.interface.is_connected:
-            print_error( "synchronizer: waiting for interface")
-            self.interface.connect_event.wait()
+        with self.lock:
+            self.running = True
+
+        while self.is_running():
+            interface = self.network.interface
+            if not interface.is_connected:
+                print_error("synchronizer: waiting for interface")
+                interface.connect_event.wait()
+                
+            self.run_interface(interface)
 
-        with self.lock: self.running = True
+
+    def run_interface(self, interface):
+
+        print_error("synchronizer: connected to", interface.server)
 
         requested_tx = []
         missing_tx = []
@@ -1423,12 +1431,10 @@ class WalletSynchronizer(threading.Thread):
             for tx_hash, tx_height in history:
                 if self.wallet.transactions.get(tx_hash) is None and (tx_hash, tx_height) not in missing_tx:
                     missing_tx.append( (tx_hash, tx_height) )
-        print_error("missing tx", missing_tx)
 
-        # wait until we are connected, in case the user is not connected
-        while not self.interface.is_connected:
-            time.sleep(1)
-        
+        if missing_tx:
+            print_error("missing tx", missing_tx)
+
         # subscriptions
         self.subscribe_to_addresses(self.wallet.addresses(True, next=True))
 
@@ -1443,12 +1449,12 @@ class WalletSynchronizer(threading.Thread):
             # request missing transactions
             for tx_hash, tx_height in missing_tx:
                 if (tx_hash, tx_height) not in requested_tx:
-                    self.interface.send([ ('blockchain.transaction.get',[tx_hash, tx_height]) ], lambda i,r: self.queue.put(r))
+                    interface.send([ ('blockchain.transaction.get',[tx_hash, tx_height]) ], lambda i,r: self.queue.put(r))
                     requested_tx.append( (tx_hash, tx_height) )
             missing_tx = []
 
             # detect if situation has changed
-            if self.interface.is_up_to_date() and self.queue.empty():
+            if interface.is_up_to_date() and self.queue.empty():
                 if not self.wallet.is_up_to_date():
                     self.wallet.set_up_to_date(True)
                     self.was_updated = True
@@ -1462,10 +1468,16 @@ class WalletSynchronizer(threading.Thread):
                 self.was_updated = False
 
             # 2. get a response
-            r = self.queue.get(block=True, timeout=10000000000)
+            try:
+                r = self.queue.get(block=True, timeout=1)
+            except Queue.Empty:
+                continue
 
-            # poke sends None. (needed during stop)
-            if not r: continue
+            if interface != self.network.interface:
+                break
+            
+            if not r:
+                continue
 
             # 3. handle response
             method = r['method']
@@ -1480,7 +1492,7 @@ class WalletSynchronizer(threading.Thread):
                 addr = params[0]
                 if self.wallet.get_status(self.wallet.get_history(addr)) != result:
                     if requested_histories.get(addr) is None:
-                        self.interface.send([('blockchain.address.get_history', [addr])], lambda i,r:self.queue.put(r))
+                        interface.send([('blockchain.address.get_history', [addr])], lambda i,r:self.queue.put(r))
                         requested_histories[addr] = result
 
             elif method == 'blockchain.address.get_history':