From 1987a76bd65aa038bdef94d98a73287bc5b46f6a Mon Sep 17 00:00:00 2001
From: Inso <insomniak.fr@gmail.com>
Date: Thu, 22 Jan 2015 22:20:44 +0100
Subject: [PATCH] Multiple bug fixing

- Managing lost communities (when no nodes could be joined)
- Fixing broadcast management
---
 src/cutecoin/core/account.py   | 13 ++++++--
 src/cutecoin/core/community.py | 60 ++++++++++++++++++++++++----------
 src/cutecoin/core/wallet.py    | 10 +++---
 src/cutecoin/gui/mainwindow.py |  5 +++
 src/cutecoin/gui/transfer.py   |  4 +++
 5 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/src/cutecoin/core/account.py b/src/cutecoin/core/account.py
index 984b7adf..90e20cfe 100644
--- a/src/cutecoin/core/account.py
+++ b/src/cutecoin/core/account.py
@@ -29,7 +29,8 @@ class Account(object):
     be locally referenced by only one account.
     '''
 
-    def __init__(self, salt, pubkey, name, communities, wallets, contacts):
+    def __init__(self, salt, pubkey, name, communities, wallets, contacts,
+                 dead_communities):
         '''
         Constructor
         '''
@@ -37,6 +38,7 @@ class Account(object):
         self.pubkey = pubkey
         self.name = name
         self.communities = communities
+        self.dead_communities = dead_communities
         self.wallets = wallets
         self.contacts = contacts
 
@@ -45,7 +47,7 @@ class Account(object):
         '''
         Constructor
         '''
-        account = cls(None, None, name, communities, wallets, [])
+        account = cls(None, None, name, communities, wallets, [], [])
         return account
 
     @classmethod
@@ -64,10 +66,15 @@ class Account(object):
             wallets.append(Wallet.load(data))
 
         communities = []
+        dead_communities = []
         for data in json_data['communities']:
+            try:
                 communities.append(Community.load(data))
+            except NoPeerAvailable:
+                dead_communities.append(data['currency'])
 
-        account = cls(salt, pubkey, name, communities, wallets, contacts)
+        account = cls(salt, pubkey, name, communities, wallets,
+                      contacts, dead_communities)
         return account
 
     def __eq__(self, other):
diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py
index 387b0a90..66ce4501 100644
--- a/src/cutecoin/core/community.py
+++ b/src/cutecoin/core/community.py
@@ -62,19 +62,14 @@ class Community(object):
         # After initializing the community from latest peers,
         # we refresh its peers tree
         logging.debug("Creating community")
-        try:
-            found_peers = self.peering()
-            for p in found_peers:
-                if p.pubkey not in [peer.pubkey for peer in peers]:
-                    self.peers.append(p)
-        except NoPeerAvailable:
-            pass
+        found_peers = self.peering()
+        for p in found_peers:
+            if p.pubkey not in [peer.pubkey for peer in self.peers]:
+                self.peers.append(p)
         logging.debug("{0} peers found".format(len(self.peers)))
+        logging.debug([peer.pubkey for peer in peers])
 
-        try:
-            self._cache.refresh()
-        except NoPeerAvailable:
-            pass
+        self._cache.refresh()
 
     @classmethod
     def create(cls, currency, peer):
@@ -209,26 +204,57 @@ class Community(object):
             req = request(e.conn_handler(), **req_args)
             try:
                 req.post(**post_args)
+                return
             except ValueError as e:
                 raise
+            except ConnectTimeout:
+                # Move the timeout peer to the end
+                self.peers.remove(peer)
+                self.peers.append(peer)
+                continue
+            except TimeoutError:
+                # Move the timeout peer to the end
+                self.peers.remove(peer)
+                self.peers.append(peer)
+                continue
             except:
-                pass
-            return
+                raise
         raise NoPeerAvailable(self.currency, len(self.peers))
 
     def broadcast(self, request, req_args={}, post_args={}):
+        tries = 0
+        ok = False
+        value_error = None
         for peer in self.peers:
             e = next(e for e in peer.endpoints if type(e) is BMAEndpoint)
             logging.debug("Trying to connect to : " + peer.pubkey)
             req = request(e.conn_handler(), **req_args)
             try:
                 req.post(**post_args)
+                ok = True
             except ValueError as e:
-                if peer == self.peers[0]:
-                    raise
+                value_error = e
+                continue
+            except ConnectTimeout:
+                tries = tries + 1
+                # Move the timeout peer to the end
+                self.peers.remove(peer)
+                self.peers.append(peer)
+                continue
+            except TimeoutError:
+                tries = tries + 1
+                # Move the timeout peer to the end
+                self.peers.remove(peer)
+                self.peers.append(peer)
+                continue
             except:
-                pass
-        raise NoPeerAvailable(self.currency, len(self.peers))
+                raise
+
+        if not ok:
+            raise value_error
+
+        if tries == len(self.peers):
+            raise NoPeerAvailable(self.currency, len(self.peers))
 
     def jsonify_peers_list(self):
         data = []
diff --git a/src/cutecoin/core/wallet.py b/src/cutecoin/core/wallet.py
index 64e788f1..7789640b 100644
--- a/src/cutecoin/core/wallet.py
+++ b/src/cutecoin/core/wallet.py
@@ -214,12 +214,10 @@ class Wallet(object):
             inputs.append(s)
             buf_inputs.remove(s)
             if value >= amount:
-                cache.available_sources = buf_inputs
-                return inputs
+                return (inputs, buf_inputs)
 
         raise NotEnoughMoneyError(value, community.currency,
                                   len(inputs), amount)
-        return []
 
     def tx_outputs(self, pubkey, amount, inputs):
         outputs = []
@@ -236,8 +234,12 @@ class Wallet(object):
 
     def send_money(self, salt, password, community,
                    recipient, amount, message):
-        inputs = self.tx_inputs(int(amount), community)
+
+        result = self.tx_inputs(int(amount), community)
+        inputs = result[0]
+        self.caches[community.currency].available_sources = result[1]
         logging.debug("Inputs : {0}".format(inputs))
+
         outputs = self.tx_outputs(recipient, amount, inputs)
         logging.debug("Outputs : {0}".format(outputs))
         tx = Transaction(PROTOCOL_VERSION, community.currency,
diff --git a/src/cutecoin/gui/mainwindow.py b/src/cutecoin/gui/mainwindow.py
index 8f7545dc..24d95b95 100644
--- a/src/cutecoin/gui/mainwindow.py
+++ b/src/cutecoin/gui/mainwindow.py
@@ -157,6 +157,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             self.action_configure_parameters.setEnabled(False)
             self.action_set_as_default.setEnabled(False)
         else:
+            for dead in self.app.current_account.dead_communities:
+                QMessageBox.critical(self, ":(",
+                            "No {0} peers could be joined. Community was lost.".format(dead),
+                            QMessageBox.Ok)
+
             self.action_set_as_default.setEnabled(self.app.current_account.name
                                                   != self.app.default_account)
             self.password_asker = PasswordAskerDialog(self.app.current_account)
diff --git a/src/cutecoin/gui/transfer.py b/src/cutecoin/gui/transfer.py
index c00149b7..458f42b9 100644
--- a/src/cutecoin/gui/transfer.py
+++ b/src/cutecoin/gui/transfer.py
@@ -70,18 +70,22 @@ class TransferMoneyDialog(QDialog, Ui_TransferMoneyDialog):
             QMessageBox.critical(self, "Money transfer",
                                  "Something wrong happened : {0}".format(e),
                                  QMessageBox.Ok)
+            return
         except NotEnoughMoneyError as e:
             QMessageBox.critical(self, "Money transfer",
                                  "You don't have enough money available in this block : \n{0}"
                                  .format(e.message))
+            return
         except NoPeerAvailable as e:
             QMessageBox.critical(self, "Money transfer",
                                  "Couldn't connect to network : {0}".format(e),
                                  QMessageBox.Ok)
+            return
         except Exception as e:
             QMessageBox.critical(self, "Error",
                                  "{0}".format(e),
                                  QMessageBox.Ok)
+            return
         self.accepted.emit()
         self.close()
 
-- 
GitLab