From f0827bb2eeec69f4ad85a34605dd04969b8e3730 Mon Sep 17 00:00:00 2001
From: inso <insomniak.fr@gmaiL.com>
Date: Mon, 16 Jan 2017 08:39:05 +0100
Subject: [PATCH] Use a pool of root servers

---
 requirements.txt                              |   1 +
 sakia.spec                                    |   3 +
 src/sakia/app.py                              |  80 ++++++--------
 src/sakia/constants.py                        |   6 ++
 src/sakia/data/processors/blockchain.py       |  14 +--
 src/sakia/data/processors/certifications.py   |   4 +-
 src/sakia/data/processors/dividends.py        |   5 +-
 src/sakia/data/processors/identities.py       |  79 +++++++++++++-
 src/sakia/data/processors/nodes.py            |  10 ++
 src/sakia/data/processors/sources.py          |   4 +-
 src/sakia/data/processors/transactions.py     |   2 +-
 src/sakia/data/repositories/meta.py           |   2 +-
 .../dialogs/connection_cfg/connection_cfg.ui  |  47 ++------
 .../gui/dialogs/connection_cfg/controller.py  |   7 +-
 src/sakia/gui/dialogs/connection_cfg/model.py | 100 ++----------------
 src/sakia/gui/navigation/model.py             |  67 +++++-------
 .../gui/sub/user_information/controller.py    |   2 +-
 src/sakia/gui/sub/user_information/model.py   |   6 +-
 src/sakia/options.py                          |  19 ++--
 src/sakia/root_servers.yml                    |   8 ++
 src/sakia/services/blockchain.py              |   3 +
 src/sakia/services/network.py                 |   3 +-
 tests/conftest.py                             |  37 ++++---
 .../functional/test_connection_cfg_dialog.py  |  15 ---
 tests/technical/test_blockchain_service.py    |   6 +-
 tests/technical/test_identities_service.py    |   8 +-
 tests/technical/test_transactions_service.py  |  20 ++--
 27 files changed, 246 insertions(+), 312 deletions(-)
 create mode 100644 src/sakia/root_servers.yml

diff --git a/requirements.txt b/requirements.txt
index 34e29cb1..6a17e851 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,3 +6,4 @@ duniter-mirage
 duniterpy>=0.40
 pytest
 pytest-asyncio
+pyyaml
\ No newline at end of file
diff --git a/sakia.spec b/sakia.spec
index 03317e0b..1cf2949c 100644
--- a/sakia.spec
+++ b/sakia.spec
@@ -29,6 +29,7 @@ if is_darwin:
                                       "libsodium.dylib")
         a.binaries = a.binaries + TOC([('lib/libsodium.dylib', libsodium_path, 'BINARY')])
     a.datas = a.datas + [('sakia/data/repositories/meta.sql', 'src/sakia/data/repositories/meta.sql', 'DATA')]
+    a.datas = a.datas + [('sakia/root_servers.yml', 'src/sakia/root_servers.yml', 'DATA')]
 
 if is_linux:
     libsodium_path = ctypes.util.find_library('libsodium.so')
@@ -40,10 +41,12 @@ if is_linux:
 
     a.binaries = a.binaries + TOC([('libsodium.so', libsodium_path, 'BINARY')])
     a.datas = a.datas + [('sakia/data/repositories/meta.sql', 'src/sakia/data/repositories/meta.sql', 'DATA')]
+    a.datas = a.datas + [('sakia/root_servers.yml', 'src/sakia/root_servers.yml', 'DATA')]
 
 if is_win:
     a.binaries = a.binaries + TOC([('libsodium.dll', ctypes.util.find_library('libsodium.dll'), 'BINARY')])
     a.datas = a.datas + [('sakia\\data\\repositories\\meta.sql', 'src\\sakia\\data\\repositories\\meta.sql', 'DATA')]
+    a.datas = a.datas + [('sakia\\root_servers.yml', 'src\\/sakia\\root_servers.yml', 'DATA')]
 
 
 print(a.binaries)
diff --git a/src/sakia/app.py b/src/sakia/app.py
index 6435732d..6022b019 100644
--- a/src/sakia/app.py
+++ b/src/sakia/app.py
@@ -33,11 +33,11 @@ class Application(QObject):
     :param sakia.data.entities.AppData app_data: the application data
     :param sakia.data.entities.UserParameters parameters: the application current user parameters
     :param sakia.data.repositories.SakiaDatabase db: The database
-    :param dict network_services: All network services for current currency
-    :param dict blockchain_services: All blockchain services for current currency
-    :param dict identities_services: All identities services for current currency
-    :param dict sources_services: All sources services for current currency
-    :param dict transactions_services: All transactions services for current currency
+    :param sakia.services.NetworkService network_service: All network services for current currency
+    :param sakia.services.BlockchainService blockchain_service: All blockchain services for current currency
+    :param sakia.services.IdentitiesService identities_service: All identities services for current currency
+    :param sakia.services.SourcesService sources_service: All sources services for current currency
+    :param sakia.Services.TransactionsService transactions_service: All transactions services for current currency
     :param sakia.services.DocumentsService documents_service: A service to broadcast documents
     """
 
@@ -55,11 +55,12 @@ class Application(QObject):
     app_data = attr.ib()
     parameters = attr.ib()
     db = attr.ib()
-    network_services = attr.ib(default=attr.Factory(dict))
-    blockchain_services = attr.ib(default=attr.Factory(dict))
-    identities_services = attr.ib(default=attr.Factory(dict))
-    sources_services = attr.ib(default=attr.Factory(dict))
-    transactions_services = attr.ib(default=attr.Factory(dict))
+    currency = attr.ib()
+    network_service = attr.ib(default=attr.Factory(dict))
+    blockchain_service = attr.ib(default=attr.Factory(dict))
+    identities_service = attr.ib(default=attr.Factory(dict))
+    sources_service = attr.ib(default=attr.Factory(dict))
+    transactions_service = attr.ib(default=attr.Factory(dict))
     documents_service = attr.ib(default=None)
     current_ref = attr.ib(default=Quantitative)
     _logger = attr.ib(default=attr.Factory(lambda:logging.getLogger('sakia')))
@@ -75,7 +76,7 @@ class Application(QObject):
     def startup(cls, argv, qapp, loop):
         options = SakiaOptions.from_arguments(argv)
         app_data = AppDataFile.in_config_path(options.config_path).load_or_init()
-        app = cls(qapp, loop, options, app_data, None, None)
+        app = cls(qapp, loop, options, app_data, None, None, options.currency)
         #app.set_proxy()
         app.get_last_version()
         app.load_profile(app_data.default)
@@ -105,40 +106,31 @@ class Application(QObject):
         sources_processor = SourcesProcessor.instanciate(self)
         transactions_processor = TransactionsProcessor.instanciate(self)
         dividends_processor = DividendsProcessor.instanciate(self)
+        nodes_processor.initialize_root_nodes(self.currency)
+        self.db.commit()
 
-        self.blockchain_services = {}
-        self.network_services = {}
-        self.identities_services = {}
-        self.sources_services = {}
-        self.transactions_services = {}
         self.documents_service = DocumentsService.instanciate(self)
-
-        for currency in self.db.connections_repo.get_currencies():
-            if currency not in self.identities_services:
-                self.identities_services[currency] = IdentitiesService(currency, connections_processor,
-                                                                   identities_processor,
-                                                                   certs_processor, blockchain_processor,
+        self.identities_service = IdentitiesService(self.currency, connections_processor,
+                                                    identities_processor,
+                                                    certs_processor, blockchain_processor,
+                                                    bma_connector)
+
+        self.transactions_service = TransactionsService(self.currency, transactions_processor,
+                                                                   dividends_processor,
+                                                                   identities_processor, connections_processor,
                                                                    bma_connector)
 
-            if currency not in self.transactions_services:
-                self.transactions_services[currency] = TransactionsService(currency, transactions_processor,
-                                                                           dividends_processor,
-                                                                           identities_processor, connections_processor,
-                                                                           bma_connector)
-
-            if currency not in self.sources_services:
-                self.sources_services[currency] = SourcesServices(currency, sources_processor,
-                                                                  connections_processor, bma_connector)
-
-            if currency not in self.blockchain_services:
-                self.blockchain_services[currency] = BlockchainService(self, currency, blockchain_processor, bma_connector,
-                                                                       self.identities_services[currency],
-                                                                       self.transactions_services[currency],
-                                                                       self.sources_services[currency])
-            if currency not in self.network_services:
-                self.network_services[currency] = NetworkService.load(self, currency, nodes_processor,
-                                                                      self.blockchain_services[currency],
-                                                                      self.identities_services[currency])
+        self.sources_service = SourcesServices(self.currency, sources_processor,
+                                                          connections_processor, bma_connector)
+
+        self.blockchain_service = BlockchainService(self, self.currency, blockchain_processor, bma_connector,
+                                                               self.identities_service,
+                                                               self.transactions_service,
+                                                               self.sources_service)
+
+        self.network_service = NetworkService.load(self, self.currency, nodes_processor,
+                                                    self.blockchain_service,
+                                                    self.identities_service)
 
     async def remove_connection(self, connection):
         await self.stop_current_profile()
@@ -179,16 +171,14 @@ class Application(QObject):
                 logging.debug("Couldn't load translation")
 
     def start_coroutines(self):
-        for currency in self.db.connections_repo.get_currencies():
-            self.network_services[currency].start_coroutines()
+        self.network_service.start_coroutines()
 
     async def stop_current_profile(self, closing=False):
         """
         Save the account to the cache
         and stop the coroutines
         """
-        for currency in self.db.connections_repo.get_currencies():
-            await self.network_services[currency].stop_coroutines(closing)
+        await self.network_service.stop_coroutines(closing)
 
     @asyncify
     async def get_last_version(self):
diff --git a/src/sakia/constants.py b/src/sakia/constants.py
index 7ec1e4f0..6daa2dd6 100644
--- a/src/sakia/constants.py
+++ b/src/sakia/constants.py
@@ -1 +1,7 @@
+import os
+import yaml
+
 MAX_CONFIRMATIONS = 6
+
+with open(os.path.join(os.path.dirname(__file__), "root_servers.yml"), 'r') as stream:
+    ROOT_SERVERS = yaml.load(stream)
diff --git a/src/sakia/data/processors/blockchain.py b/src/sakia/data/processors/blockchain.py
index 5b2ae605..11913da7 100644
--- a/src/sakia/data/processors/blockchain.py
+++ b/src/sakia/data/processors/blockchain.py
@@ -26,6 +26,9 @@ class BlockchainProcessor:
         return cls(app.db.blockchains_repo,
                    BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
+    def initialized(self, currency):
+        return self._repo.get_one(currency=currency) is not None
+
     async def timestamp(self, currency, block_number):
         try:
             block = await self._bma_connector.get(currency, bma.blockchain.block, {'number': block_number})
@@ -139,7 +142,6 @@ class BlockchainProcessor:
             block_doc = Block.from_signed_raw("{0}{1}\n".format(block['raw'], block['signature']))
             return block_doc
 
-
     async def new_blocks_with_identities(self, currency):
         """
         Get blocks more recent than local blockuid
@@ -209,7 +211,7 @@ class BlockchainProcessor:
             blockchain = Blockchain(currency=currency)
             log_stream("Requesting blockchain parameters")
             try:
-                parameters = await self._bma_connector.get(currency, bma.blockchain.parameters, verify=False)
+                parameters = await self._bma_connector.get(currency, bma.blockchain.parameters)
                 blockchain.parameters.ms_validity = parameters['msValidity']
                 blockchain.parameters.avg_gen_time = parameters['avgGenTime']
                 blockchain.parameters.c = parameters['c']
@@ -233,7 +235,7 @@ class BlockchainProcessor:
 
         log_stream("Requesting current block")
         try:
-            current_block = await self._bma_connector.get(currency, bma.blockchain.current, verify=False)
+            current_block = await self._bma_connector.get(currency, bma.blockchain.current)
             signed_raw = "{0}{1}\n".format(current_block['raw'], current_block['signature'])
             block = Block.from_signed_raw(signed_raw)
             blockchain.current_buid = block.blockUID
@@ -244,7 +246,7 @@ class BlockchainProcessor:
                 raise
 
         log_stream("Requesting blocks with dividend")
-        with_ud = await self._bma_connector.get(currency, bma.blockchain.ud, verify=False)
+        with_ud = await self._bma_connector.get(currency, bma.blockchain.ud)
         blocks_with_ud = with_ud['result']['blocks']
 
         if len(blocks_with_ud) > 0:
@@ -253,7 +255,7 @@ class BlockchainProcessor:
                 index = max(len(blocks_with_ud) - 1, 0)
                 block_number = blocks_with_ud[index]
                 block_with_ud = await self._bma_connector.get(currency, bma.blockchain.block,
-                                                              req_args={'number': block_number}, verify=False)
+                                                              req_args={'number': block_number})
                 if block_with_ud:
                     blockchain.last_members_count = block_with_ud['membersCount']
                     blockchain.last_ud = block_with_ud['dividend']
@@ -269,7 +271,7 @@ class BlockchainProcessor:
                 index = max(len(blocks_with_ud) - 2, 0)
                 block_number = blocks_with_ud[index]
                 block_with_ud = await self._bma_connector.get(currency, bma.blockchain.block,
-                                                              req_args={'number': block_number}, verify=False)
+                                                              req_args={'number': block_number})
                 blockchain.previous_mass = block_with_ud['monetaryMass']
                 blockchain.previous_members_count = block_with_ud['membersCount']
                 blockchain.previous_ud = block_with_ud['dividend']
diff --git a/src/sakia/data/processors/certifications.py b/src/sakia/data/processors/certifications.py
index 833acf27..c1591087 100644
--- a/src/sakia/data/processors/certifications.py
+++ b/src/sakia/data/processors/certifications.py
@@ -103,7 +103,7 @@ class CertificationsProcessor:
         certifiers = list()
         try:
             data = await self._bma_connector.get(identity.currency, bma.wot.certifiers_of,
-                                                 req_args={'search': identity.pubkey}, verify=False)
+                                                 req_args={'search': identity.pubkey})
 
             for certifier_data in data['certifications']:
                 certification = Certification(currency=identity.currency,
@@ -132,7 +132,7 @@ class CertificationsProcessor:
         certified = list()
         try:
             data = await self._bma_connector.get(identity.currency, bma.wot.certified_by,
-                                                 req_args={'search': identity.pubkey}, verify=False)
+                                                 req_args={'search': identity.pubkey})
             for certified_data in data['certifications']:
                 certification = Certification(currency=identity.currency,
                                               certifier=identity.pubkey,
diff --git a/src/sakia/data/processors/dividends.py b/src/sakia/data/processors/dividends.py
index 5c10168f..a9d7e975 100644
--- a/src/sakia/data/processors/dividends.py
+++ b/src/sakia/data/processors/dividends.py
@@ -44,7 +44,7 @@ class DividendsProcessor:
         :param function log_stream:
         """
         history_data = await self._bma_connector.get(connection.currency, bma.ud.history,
-                                                     req_args={'pubkey': connection.pubkey}, verify=False)
+                                                     req_args={'pubkey': connection.pubkey})
         log_stream("Found {0} available dividends".format(len(history_data["history"]["history"])))
         block_numbers = []
         for ud_data in history_data["history"]["history"]:
@@ -66,8 +66,7 @@ class DividendsProcessor:
             for input in txdoc.inputs:
                 if input.source == "D" and input.origin_id == connection.pubkey and input.index not in block_numbers:
                     block = await self._bma_connector.get(connection.currency,
-                                                          bma.blockchain.block, req_args={'number': input.index},
-                                                          verify=False)
+                                                          bma.blockchain.block, req_args={'number': input.index})
                     await asyncio.sleep(0.5)
 
                     dividend = Dividend(currency=connection.currency,
diff --git a/src/sakia/data/processors/identities.py b/src/sakia/data/processors/identities.py
index d0a535ce..29656f89 100644
--- a/src/sakia/data/processors/identities.py
+++ b/src/sakia/data/processors/identities.py
@@ -135,7 +135,7 @@ class IdentitiesProcessor:
         log_stream("Requesting membership data")
         try:
             memberships_data = await self._bma_connector.get(identity.currency, bma.blockchain.memberships,
-                                                             req_args={'search': identity.pubkey}, verify=False)
+                                                             req_args={'search': identity.pubkey})
             if block_uid(memberships_data['sigDate']) == identity.blockstamp \
                and memberships_data['uid'] == identity.uid:
                 identity.written = True
@@ -147,15 +147,14 @@ class IdentitiesProcessor:
                 if identity.membership_buid:
                     log_stream("Requesting membership timestamp")
                     ms_block_data = await self._bma_connector.get(identity.currency, bma.blockchain.block,
-                                                                  req_args={'number': identity.membership_buid.number},
-                                                                  verify=False)
+                                                                  req_args={'number': identity.membership_buid.number})
                     if ms_block_data:
                         identity.membership_timestamp = ms_block_data['medianTime']
 
                 log_stream("Requesting identity requirements status")
 
                 requirements_data = await self._bma_connector.get(identity.currency, bma.wot.requirements,
-                                                                  req_args={'search': identity.pubkey}, verify=False)
+                                                                  req_args={'search': identity.pubkey})
                 identity_data = next((data for data in requirements_data["identities"]
                                       if data["pubkey"] == identity.pubkey))
                 identity.member = identity_data['membershipExpiresIn'] > 0 and not identity_data['outdistanced']
@@ -168,6 +167,78 @@ class IdentitiesProcessor:
             else:
                 raise
 
+    async def check_registered(self, connection):
+        """
+        Checks for the pubkey and the uid of an account on a given node
+        :return: (True if found, local value, network value)
+        """
+        identity = Identity(connection.currency, connection.pubkey, connection.uid)
+        found_identity = Identity(connection.currency, connection.pubkey, connection.uid)
+
+        def _parse_uid_lookup(data):
+            timestamp = BlockUID.empty()
+            found_uid = ""
+            for result in data['results']:
+                if result["pubkey"] == identity.pubkey:
+                    uids = result['uids']
+                    for uid_data in uids:
+                        if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp:
+                            timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"])
+                            found_identity.blockstamp = timestamp
+                            found_uid = uid_data["uid"]
+                            found_identity.signature = uid_data["self"]
+            return identity.uid == found_uid, identity.uid, found_uid
+
+        def _parse_pubkey_lookup(data):
+            timestamp = BlockUID.empty()
+            found_uid = ""
+            found_result = ["", ""]
+            for result in data['results']:
+                uids = result['uids']
+                for uid_data in uids:
+                    if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp:
+                        timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"])
+                        found_identity.blockstamp = timestamp
+                        found_uid = uid_data["uid"]
+                        found_identity.signature = uid_data["self"]
+                if found_uid == identity.uid:
+                    found_result = result['pubkey'], found_uid
+            if found_result[1] == identity.uid:
+                return identity.pubkey == found_result[0], identity.pubkey, found_result[0]
+            else:
+                return False, identity.pubkey, None
+
+        async def execute_requests(parser, search):
+            tries = 0
+            nonlocal registered
+            try:
+                data = await self._bma_connector.get(connection.currency, bma.wot.lookup,
+                                                      req_args={'search': search})
+                if data:
+                    registered = parser(data)
+                tries += 1
+            except errors.DuniterError as e:
+                if e.ucode in (errors.NO_MEMBER_MATCHING_PUB_OR_UID, errors.NO_MATCHING_IDENTITY):
+                        tries += 1
+                else:
+                    raise
+
+        # cell 0 contains True if the user is already registered
+        # cell 1 contains the uid/pubkey selected locally
+        # cell 2 contains the uid/pubkey found on the network
+        registered = (False, identity.uid, None)
+
+        # We execute search based on pubkey
+        # And look for account UID
+        await execute_requests(_parse_uid_lookup, identity.pubkey)
+
+        # If the uid wasn't found when looking for the pubkey
+        # We look for the uid and check for the pubkey
+        if not registered[0] and not registered[2] and identity.uid:
+            await execute_requests(_parse_pubkey_lookup, identity.uid)
+
+        return registered, found_identity
+
     def cleanup_connection(self, connection):
         """
         Cleanup after connection removal
diff --git a/src/sakia/data/processors/nodes.py b/src/sakia/data/processors/nodes.py
index d5d92bf0..fff1d9d4 100644
--- a/src/sakia/data/processors/nodes.py
+++ b/src/sakia/data/processors/nodes.py
@@ -1,5 +1,6 @@
 import attr
 import sqlite3
+from sakia.constants import ROOT_SERVERS
 from ..entities import Node
 from duniterpy.documents import BlockUID, endpoint
 import logging
@@ -13,6 +14,15 @@ class NodesProcessor:
     def instanciate(cls, app):
         return cls(app.db.nodes_repo)
 
+    def initialize_root_nodes(self, currency):
+        if not self.nodes(currency):
+            for pubkey in ROOT_SERVERS[currency]:
+                node = Node(currency=currency,
+                            pubkey=pubkey,
+                            endpoints=ROOT_SERVERS[currency][pubkey],
+                            peer_blockstamp=BlockUID.empty())
+                self._repo.insert(node)
+
     def current_buid(self, currency):
         """
         Get current buid
diff --git a/src/sakia/data/processors/sources.py b/src/sakia/data/processors/sources.py
index 36055a5a..70e47005 100644
--- a/src/sakia/data/processors/sources.py
+++ b/src/sakia/data/processors/sources.py
@@ -28,7 +28,7 @@ class SourcesProcessor:
         try:
             self._repo.insert(source)
         except sqlite3.IntegrityError:
-            self._repo.update(source)
+            self._logger.debug("Source already known : {0}".format(source.identifier))
 
     async def initialize_sources(self, currency, pubkey, log_stream):
         """
@@ -37,7 +37,7 @@ class SourcesProcessor:
         log_stream("Requesting sources")
         try:
             sources_data = await self._bma_connector.get(currency, bma.tx.sources,
-                                                         req_args={'pubkey': pubkey}, verify=False)
+                                                         req_args={'pubkey': pubkey})
 
             log_stream("Found {0} sources".format(len(sources_data['sources'])))
             for i, s in enumerate(sources_data['sources']):
diff --git a/src/sakia/data/processors/transactions.py b/src/sakia/data/processors/transactions.py
index 649b261b..193fc4d2 100644
--- a/src/sakia/data/processors/transactions.py
+++ b/src/sakia/data/processors/transactions.py
@@ -134,7 +134,7 @@ class TransactionsProcessor:
         :param function log_stream:
         """
         history_data = await self._bma_connector.get(connection.currency, bma.tx.history,
-                                                     req_args={'pubkey': connection.pubkey}, verify=False)
+                                                     req_args={'pubkey': connection.pubkey})
         txid = 0
         nb_tx = len(history_data["history"]["sent"]) + len(history_data["history"]["received"])
         log_stream("Found {0} transactions".format(nb_tx))
diff --git a/src/sakia/data/repositories/meta.py b/src/sakia/data/repositories/meta.py
index 4bae0a53..74d5195e 100644
--- a/src/sakia/data/repositories/meta.py
+++ b/src/sakia/data/repositories/meta.py
@@ -34,7 +34,7 @@ class SakiaDatabase:
         sqlite3.register_adapter(BlockUID, str)
         sqlite3.register_adapter(bool, int)
         sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
-        con = sqlite3.connect(os.path.join(options.config_path, profile_name, options.database + ".db"),
+        con = sqlite3.connect(os.path.join(options.config_path, profile_name, options.currency + ".db"),
                               detect_types=sqlite3.PARSE_DECLTYPES)
         meta = SakiaDatabase(con, ConnectionsRepo(con), IdentitiesRepo(con),
                              BlockchainsRepo(con), CertificationsRepo(con), TransactionsRepo(con),
diff --git a/src/sakia/gui/dialogs/connection_cfg/connection_cfg.ui b/src/sakia/gui/dialogs/connection_cfg/connection_cfg.ui
index a70c6198..4db97ce8 100644
--- a/src/sakia/gui/dialogs/connection_cfg/connection_cfg.ui
+++ b/src/sakia/gui/dialogs/connection_cfg/connection_cfg.ui
@@ -24,47 +24,6 @@
      </property>
      <widget class="QWidget" name="page_node">
       <layout class="QVBoxLayout" name="verticalLayout_12">
-       <item>
-        <widget class="QLabel" name="label_2">
-         <property name="text">
-          <string>Please enter the address of a node :</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_10">
-         <property name="rightMargin">
-          <number>5</number>
-         </property>
-         <item>
-          <widget class="QLineEdit" name="edit_server"/>
-         </item>
-         <item>
-          <widget class="QLabel" name="label_double_dot">
-           <property name="text">
-            <string>:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QSpinBox" name="spinbox_port">
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="value">
-            <number>8001</number>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QCheckBox" name="checkbox_secured">
-           <property name="text">
-            <string>SSL/TLS</string>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
        <item>
         <layout class="QVBoxLayout" name="verticalLayout_13">
          <property name="topMargin">
@@ -233,6 +192,9 @@
               <property name="text">
                <string/>
               </property>
+              <property name="echoMode">
+               <enum>QLineEdit::Password</enum>
+              </property>
               <property name="placeholderText">
                <string>Secret key</string>
               </property>
@@ -240,6 +202,9 @@
             </item>
             <item>
              <widget class="QLineEdit" name="edit_salt_bis">
+              <property name="echoMode">
+               <enum>QLineEdit::Password</enum>
+              </property>
               <property name="placeholderText">
                <string>Please repeat your secret key</string>
               </property>
diff --git a/src/sakia/gui/dialogs/connection_cfg/controller.py b/src/sakia/gui/dialogs/connection_cfg/controller.py
index f9c7d094..49f2a824 100644
--- a/src/sakia/gui/dialogs/connection_cfg/controller.py
+++ b/src/sakia/gui/dialogs/connection_cfg/controller.py
@@ -124,9 +124,7 @@ class ConnectionConfigController(QObject):
                 try:
                     self.view.button_connect.setEnabled(False)
                     self.view.button_register.setEnabled(False)
-                    await self.model.create_connection(self.view.edit_server.text(),
-                                                       self.view.spinbox_port.value(),
-                                                       self.view.checkbox_secured.isChecked())
+                    await self.model.create_connection()
                     self.password_asker = PasswordAskerDialog(self.model.connection)
                 except (DisconnectedError, ClientError, MalformedDocumentError, ValueError, TimeoutError) as e:
                     self._logger.debug(str(e))
@@ -155,7 +153,6 @@ class ConnectionConfigController(QObject):
             self.view.stacked_pages.setCurrentWidget(self.view.page_connection)
             connection_identity = await self.step_key
 
-        self.model.insert_or_update_connector()
         self.view.stacked_pages.setCurrentWidget(self.view.page_services)
         self.view.progress_bar.setValue(0)
         self.view.progress_bar.setMaximum(3)
@@ -199,8 +196,6 @@ class ConnectionConfigController(QObject):
             self._logger.debug("Validate changes")
             self.model.insert_or_update_connection()
             self.model.app.db.commit()
-            if self.model.node_connector:
-                await self.model.node_connector.session.close()
         except (NoPeerAvailable, DuniterError, StopIteration) as e:
             if not isinstance(e, StopIteration):
                 self.view.show_error(self.model.notification(), str(e))
diff --git a/src/sakia/gui/dialogs/connection_cfg/model.py b/src/sakia/gui/dialogs/connection_cfg/model.py
index 2ab5ec9b..2701ab3b 100644
--- a/src/sakia/gui/dialogs/connection_cfg/model.py
+++ b/src/sakia/gui/dialogs/connection_cfg/model.py
@@ -6,7 +6,7 @@ from duniterpy.key import SigningKey
 from sakia.data.entities import Connection, Identity, Node
 from sakia.data.connectors import NodeConnector
 from sakia.data.processors import ConnectionsProcessor, NodesProcessor, BlockchainProcessor, \
-    SourcesProcessor, CertificationsProcessor, TransactionsProcessor, DividendsProcessor
+    SourcesProcessor, CertificationsProcessor, TransactionsProcessor, DividendsProcessor, IdentitiesProcessor
 
 
 class ConnectionConfigModel(QObject):
@@ -26,19 +26,10 @@ class ConnectionConfigModel(QObject):
         super().__init__(parent)
         self.app = app
         self.connection = connection
-        self.node_connector = node_connector
         self.identities_processor = identities_processor
 
-    async def create_connection(self, server, port, secured):
-        node_connector = await NodeConnector.from_address(None, secured, server, port,
-                                                               user_parameters=self.app.parameters)
-        currencies = self.app.db.connections_repo.get_currencies()
-        if len(currencies) > 0 and node_connector.node.currency != currencies[0]:
-            raise ValueError("""This node is running for {0} network.<br/>
-Current database is storing {1} network.""".format(node_connector.node.currency, currencies[0]))
-        self.node_connector = node_connector
-        self.connection = Connection(self.node_connector.node.currency, "", "")
-        self.node_connector.node.state = Node.ONLINE
+    async def create_connection(self):
+        self.connection = Connection(self.app.currency, "", "")
 
     def notification(self):
         return self.app.parameters.notifications
@@ -54,9 +45,6 @@ Current database is storing {1} network.""".format(node_connector.node.currency,
         self.connection.password = password
         self.connection.pubkey = SigningKey(self.connection.salt, password, scrypt_params).pubkey
 
-    def insert_or_update_connector(self):
-        NodesProcessor(self.app.db.nodes_repo).commit_node(self.node_connector.node)
-
     def insert_or_update_connection(self):
         ConnectionsProcessor(self.app.db.connections_repo).commit_connection(self.connection)
 
@@ -70,7 +58,7 @@ Current database is storing {1} network.""".format(node_connector.node.currency,
         :return:
         """
         blockchain_processor = BlockchainProcessor.instanciate(self.app)
-        await blockchain_processor.initialize_blockchain(self.node_connector.node.currency, log_stream)
+        await blockchain_processor.initialize_blockchain(self.app.currency, log_stream)
 
     async def initialize_sources(self, log_stream):
         """
@@ -79,7 +67,7 @@ Current database is storing {1} network.""".format(node_connector.node.currency,
         :return:
         """
         sources_processor = SourcesProcessor.instanciate(self.app)
-        await sources_processor.initialize_sources(self.node_connector.node.currency, self.connection.pubkey, log_stream)
+        await sources_processor.initialize_sources(self.app.currency, self.connection.pubkey, log_stream)
 
     async def initialize_identity(self, identity, log_stream):
         """
@@ -128,82 +116,8 @@ Current database is storing {1} network.""".format(node_connector.node.currency,
         return await self.app.documents_service.broadcast_identity(self.connection, self.connection.password)
 
     async def check_registered(self):
-        """
-        Checks for the pubkey and the uid of an account on a given node
-        :return: (True if found, local value, network value)
-        """
-        identity = Identity(self.connection.currency, self.connection.pubkey, self.connection.uid)
-        found_identity = Identity(self.connection.currency, self.connection.pubkey, self.connection.uid)
-
-        def _parse_uid_lookup(data):
-            timestamp = BlockUID.empty()
-            found_uid = ""
-            for result in data['results']:
-                if result["pubkey"] == identity.pubkey:
-                    uids = result['uids']
-                    for uid_data in uids:
-                        if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp:
-                            timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"])
-                            found_identity.blockstamp = timestamp
-                            found_uid = uid_data["uid"]
-                            found_identity.signature = uid_data["self"]
-            return identity.uid == found_uid, identity.uid, found_uid
-
-        def _parse_pubkey_lookup(data):
-            timestamp = BlockUID.empty()
-            found_uid = ""
-            found_result = ["", ""]
-            for result in data['results']:
-                uids = result['uids']
-                for uid_data in uids:
-                    if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp:
-                        timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"])
-                        found_identity.blockstamp = timestamp
-                        found_uid = uid_data["uid"]
-                        found_identity.signature = uid_data["self"]
-                if found_uid == identity.uid:
-                    found_result = result['pubkey'], found_uid
-            if found_result[1] == identity.uid:
-                return identity.pubkey == found_result[0], identity.pubkey, found_result[0]
-            else:
-                return False, identity.pubkey, None
-
-        async def execute_requests(parser, search):
-            tries = 0
-            nonlocal registered
-            for endpoint in [e for e in self.node_connector.node.endpoints
-                             if isinstance(e, BMAEndpoint) or isinstance(e, SecuredBMAEndpoint)]:
-                if not registered[0] and not registered[2]:
-                    try:
-                        data = await self.node_connector.safe_request(endpoint, bma.wot.lookup,
-                                                                      req_args={'search': search},
-                                                                      proxy=self.app.parameters.proxy())
-                        if data:
-                            registered = parser(data)
-                        tries += 1
-                    except errors.DuniterError as e:
-                        if e.ucode in (errors.NO_MEMBER_MATCHING_PUB_OR_UID, errors.NO_MATCHING_IDENTITY):
-                                tries += 1
-                        else:
-                            raise
-                else:
-                    break
-
-        # cell 0 contains True if the user is already registered
-        # cell 1 contains the uid/pubkey selected locally
-        # cell 2 contains the uid/pubkey found on the network
-        registered = (False, identity.uid, None)
-
-        # We execute search based on pubkey
-        # And look for account UID
-        await execute_requests(_parse_uid_lookup, identity.pubkey)
-
-        # If the uid wasn't found when looking for the pubkey
-        # We look for the uid and check for the pubkey
-        if not registered[0] and not registered[2] and identity.uid:
-            await execute_requests(_parse_pubkey_lookup, identity.uid)
-
-        return registered, found_identity
+        identities_processor = IdentitiesProcessor.instanciate(self.app)
+        return await identities_processor.check_registered(self.connection)
 
     def key_exists(self):
         return self.connection.pubkey in ConnectionsProcessor.instanciate(self.app).pubkeys()
diff --git a/src/sakia/gui/navigation/model.py b/src/sakia/gui/navigation/model.py
index fa1c9703..d74f2dc4 100644
--- a/src/sakia/gui/navigation/model.py
+++ b/src/sakia/gui/navigation/model.py
@@ -22,32 +22,19 @@ class NavigationModel(QObject):
         self._current_data = None
 
     def init_navigation_data(self):
-        currencies = ConnectionsProcessor.instanciate(self.app).currencies()
-        if currencies:
-            self.navigation = [
-                {
-                    'title': self.tr('Network'),
-                    'icon': ':/icons/network_icon',
-                    'component': "Network",
-                    'dependencies': {
-                        'network_service': self.app.network_services[currencies[0]],
-                    },
-                    'misc': {
-                    },
-                    'children': []
-                }
-            ]
-        else:
-            self.navigation = [
-                {
-                    'title': self.tr("No connection configured"),
-                    'component': "HomeScreen",
-                    'parameters': self.app.parameters,
-                    'dependencies': {},
-                    'misc': {},
-                    'children': []
-                }
-            ]
+        self.navigation = [
+            {
+                'title': self.tr('Network'),
+                'icon': ':/icons/network_icon',
+                'component': "Network",
+                'dependencies': {
+                    'network_service': self.app.network_service,
+                },
+                'misc': {
+                },
+                'children': []
+            }
+        ]
 
         self._current_data = self.navigation[0]
         for connection in self.app.db.connections_repo.get_all():
@@ -59,9 +46,9 @@ class NavigationModel(QObject):
             'title': connection.title(),
             'component': "Informations",
             'dependencies': {
-                'blockchain_service': self.app.blockchain_services[connection.currency],
-                'identities_service': self.app.identities_services[connection.currency],
-                'sources_service': self.app.sources_services[connection.currency],
+                'blockchain_service': self.app.blockchain_service,
+                'identities_service': self.app.identities_service,
+                'sources_service': self.app.sources_service,
                 'connection': connection,
             },
             'misc': {
@@ -74,10 +61,10 @@ class NavigationModel(QObject):
                     'component': "TxHistory",
                     'dependencies': {
                         'connection': connection,
-                        'identities_service': self.app.identities_services[connection.currency],
-                        'blockchain_service': self.app.blockchain_services[connection.currency],
-                        'transactions_service': self.app.transactions_services[connection.currency],
-                        "sources_service": self.app.sources_services[connection.currency]
+                        'identities_service': self.app.identities_service,
+                        'blockchain_service': self.app.blockchain_service,
+                        'transactions_service': self.app.transactions_service,
+                        "sources_service": self.app.sources_service
                     },
                     'misc': {
                         'connection': connection
@@ -92,8 +79,8 @@ class NavigationModel(QObject):
                 'component': "Identities",
                 'dependencies': {
                     'connection': connection,
-                    'blockchain_service': self.app.blockchain_services[connection.currency],
-                    'identities_service': self.app.identities_services[connection.currency],
+                    'blockchain_service': self.app.blockchain_service,
+                    'identities_service': self.app.identities_service,
                 },
                 'misc': {
                     'connection': connection
@@ -105,8 +92,8 @@ class NavigationModel(QObject):
                 'component': "Wot",
                 'dependencies': {
                     'connection': connection,
-                    'blockchain_service': self.app.blockchain_services[connection.currency],
-                    'identities_service': self.app.identities_services[connection.currency],
+                    'blockchain_service': self.app.blockchain_service,
+                    'identities_service': self.app.identities_service,
                 },
                 'misc': {
                     'connection': connection
@@ -138,12 +125,10 @@ class NavigationModel(QObject):
         return self.app.documents_service.generate_revokation(connection, password)
 
     def identity_published(self, connection):
-        identities_services = self.app.identities_services[connection.currency]
-        return identities_services.get_identity(connection.pubkey, connection.uid).written
+        return self.app.identities_service.get_identity(connection.pubkey, connection.uid).written
 
     def identity_is_member(self, connection):
-        identities_services = self.app.identities_services[connection.currency]
-        return identities_services.get_identity(connection.pubkey, connection.uid).member
+        return self.app.identities_services.get_identity(connection.pubkey, connection.uid).member
 
     async def remove_connection(self, connection):
         await self.app.remove_connection(connection)
diff --git a/src/sakia/gui/sub/user_information/controller.py b/src/sakia/gui/sub/user_information/controller.py
index 5ffb47cc..9a86ef27 100644
--- a/src/sakia/gui/sub/user_information/controller.py
+++ b/src/sakia/gui/sub/user_information/controller.py
@@ -49,7 +49,7 @@ class UserInformationController(QObject):
         tabwidget = QTabWidget(dialog)
         layout.addWidget(tabwidget)
 
-        identities = await app.identities_services[currency].lookup(pubkey)
+        identities = await app.identities_service.lookup(pubkey)
         for i in identities:
             user_info = cls.create(parent, app, currency, i)
             user_info.refresh()
diff --git a/src/sakia/gui/sub/user_information/model.py b/src/sakia/gui/sub/user_information/model.py
index 77511222..20a478f0 100644
--- a/src/sakia/gui/sub/user_information/model.py
+++ b/src/sakia/gui/sub/user_information/model.py
@@ -22,13 +22,10 @@ class UserInformationModel(QObject):
         self.app = app
         self.currency = currency
         self.identity = identity
+        self.identities_service = self.app.identities_service
         if identity:
             self.certs_sent = self._certifications_processor.certifications_sent(currency, identity.pubkey)
             self.certs_received = self._certifications_processor.certifications_received(currency, identity.pubkey)
-        if currency:
-            self.identities_service = self.app.identities_services[self.currency]
-        else:
-            self.identities_service = None
 
     async def load_identity(self, identity):
         """
@@ -40,7 +37,6 @@ class UserInformationModel(QObject):
 
     def set_currency(self, currency):
         self.currency = currency
-        self.identities_service = self.app.identities_services[self.currency]
 
     async def nb_certs(self):
         certs = await self.identities_service.load_certifiers_of(self.identity)
diff --git a/src/sakia/options.py b/src/sakia/options.py
index 506598ac..3690368f 100644
--- a/src/sakia/options.py
+++ b/src/sakia/options.py
@@ -1,11 +1,6 @@
-"""
-Created on 7 févr. 2014
-
-@author: inso
-"""
-
 import attr
 import logging
+from sakia.constants import ROOT_SERVERS
 from logging import FileHandler, StreamHandler
 from logging.handlers import RotatingFileHandler
 from optparse import OptionParser
@@ -27,7 +22,7 @@ def config_path_factory():
 @attr.s()
 class SakiaOptions:
     config_path = attr.ib(default=attr.Factory(config_path_factory))
-    database = attr.ib(default="sakia")
+    currency = attr.ib(default="fakenet")
     _logger = attr.ib(default=attr.Factory(lambda: logging.getLogger('sakia')))
 
     @classmethod
@@ -51,13 +46,15 @@ class SakiaOptions:
                           action="store_true", dest="debug", default=False,
                           help="Print DEBUG messages to stdout")
 
-        parser.add_option("--database",  dest="database", default="sakia",
-                          help="Select another database filename")
+        parser.add_option("--currency",  dest="currency", default="fakenet",
+                          help="Select a currency between {0}".format(",".join(ROOT_SERVERS.keys())))
 
         (options, args) = parser.parse_args(argv)
 
-        if options.database:
-            self.database = options.database
+        if options.currency not in ROOT_SERVERS.keys():
+            raise RuntimeError("{0} is not a valid currency".format(options.currency))
+        else:
+            self.currency = options.currency
 
         if options.debug:
             self._logger.setLevel(logging.DEBUG)
diff --git a/src/sakia/root_servers.yml b/src/sakia/root_servers.yml
new file mode 100644
index 00000000..79e29f02
--- /dev/null
+++ b/src/sakia/root_servers.yml
@@ -0,0 +1,8 @@
+fakenet:
+  HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:
+    - "BASIC_MERKLED_API fakenet.cgeek.fr 10900"
+test_net:
+  8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU:
+    - "BASIC_MERKLED_API testnet.duniter.inso.ovh 80"
+  BSmbyQCeRxoEami1ta6h67ZoVHs4KpudZ6VaSdpprbZP:
+    - "BASIC_MERKLED_API testnet.duniter.org 8999"
diff --git a/src/sakia/services/blockchain.py b/src/sakia/services/blockchain.py
index 561b80a0..5666a55a 100644
--- a/src/sakia/services/blockchain.py
+++ b/src/sakia/services/blockchain.py
@@ -33,6 +33,9 @@ class BlockchainService(QObject):
         self._sources_service = sources_service
         self._logger = logging.getLogger('sakia')
 
+    def initialized(self):
+        return self._blockchain_processor.initialized(self.app.currency)
+
     def handle_new_blocks(self, blocks):
         self._blockchain_processor.handle_new_blocks(self.currency, blocks)
 
diff --git a/src/sakia/services/network.py b/src/sakia/services/network.py
index 472a72b6..141db674 100644
--- a/src/sakia/services/network.py
+++ b/src/sakia/services/network.py
@@ -72,6 +72,7 @@ class NetworkService(QObject):
         :param sakia.data.processors.NodeProcessor node_processor: The nodes processor
         :return:
         """
+
         connectors = []
         for node in node_processor.nodes(currency):
             connectors.append(NodeConnector(node, app.parameters))
@@ -211,7 +212,7 @@ class NetworkService(QObject):
                         self.nodes_changed.emit()
                     except InvalidNodeCurrency as e:
                         self._logger.debug(str(e))
-                if node:
+                if node and self._blockchain_service.initialized():
                     try:
                         identity = await self._identities_service.find_from_pubkey(node.pubkey)
                         identity = await self._identities_service.load_requirements(identity)
diff --git a/tests/conftest.py b/tests/conftest.py
index 859ae71a..7f2bbbea 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -67,18 +67,31 @@ def user_parameters():
 @pytest.fixture
 def application(event_loop, meta_repo, sakia_options, app_data, user_parameters):
     app = Application(qapp=get_application(),
-                       loop=event_loop,
-                       options=sakia_options,
-                       app_data=app_data,
-                       parameters=user_parameters,
-                       db=meta_repo)
+                      loop=event_loop,
+                      options=sakia_options,
+                      app_data=app_data,
+                      parameters=user_parameters,
+                      db=meta_repo,
+                      currency="test_currency")
     app.documents_service = DocumentsService.instanciate(app)
     return app
 
 
 @pytest.fixture
-def fake_server(event_loop):
-    return event_loop.run_until_complete(mirage.Node.start(None, "test_currency", "12356", "123456", event_loop))
+def fake_server(application, event_loop):
+    server = event_loop.run_until_complete(mirage.Node.start(None, "test_currency", "12356", "123456", event_loop))
+
+    application.db.nodes_repo.insert(Node(currency=server.forge.currency,
+                                          pubkey=server.forge.key.pubkey,
+                                          endpoints=server.peer_doc().endpoints,
+                                          peer_blockstamp=server.peer_doc().blockUID,
+                                          uid="",
+                                          current_buid=BlockUID.empty(),
+                                          current_ts=0,
+                                          state=Node.ONLINE,
+                                          software="duniter",
+                                          version="0.40.2"))
+    return server
 
 
 @pytest.fixture
@@ -180,16 +193,6 @@ def application_with_one_connection(application, simple_fake_server, bob):
                             membership_written_on=simple_fake_server.forge.blocks[bob_ms.written_on].number)
     application.db.identities_repo.insert(bob_identity)
     application.instanciate_services()
-    application.db.nodes_repo.insert(Node(currency=simple_fake_server.forge.currency,
-                                          pubkey=simple_fake_server.forge.key.pubkey,
-                                          endpoints=simple_fake_server.peer_doc().endpoints,
-                                          peer_blockstamp=simple_fake_server.peer_doc().blockUID,
-                                          uid="",
-                                          current_buid=BlockUID(current_block.number, current_block.sha_hash),
-                                          current_ts=current_block.mediantime,
-                                          state=Node.ONLINE,
-                                          software="duniter",
-                                          version="0.40.2"))
     application.switch_language()
 
     return application
diff --git a/tests/functional/test_connection_cfg_dialog.py b/tests/functional/test_connection_cfg_dialog.py
index f9f50c56..9cc0a879 100644
--- a/tests/functional/test_connection_cfg_dialog.py
+++ b/tests/functional/test_connection_cfg_dialog.py
@@ -35,10 +35,6 @@ async def test_register_empty_blockchain(application, fake_server, bob):
             connection_config_dialog.view.close()
 
     async def exec_test():
-        QTest.keyClicks(connection_config_dialog.view.edit_server, fake_server.peer_doc().endpoints[0].ipv4)
-        connection_config_dialog.view.spinbox_port.setValue(fake_server.peer_doc().endpoints[0].port)
-        assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_node
-        await asyncio.sleep(0.6)
         QTest.mouseClick(connection_config_dialog.view.button_register, Qt.LeftButton)
         await asyncio.sleep(0.6)
 
@@ -65,9 +61,6 @@ async def test_connect(application, simple_fake_server, bob):
             connection_config_dialog.view.close()
 
     async def exec_test():
-        QTest.keyClicks(connection_config_dialog.view.edit_server, simple_fake_server.peer_doc().endpoints[0].ipv4)
-        connection_config_dialog.view.spinbox_port.setValue(simple_fake_server.peer_doc().endpoints[0].port)
-        assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_node
         QTest.mouseClick(connection_config_dialog.view.button_connect, Qt.LeftButton)
         await asyncio.sleep(1)
 
@@ -94,10 +87,6 @@ async def test_connect_wrong_uid(application, simple_fake_server, wrong_bob_uid,
             connection_config_dialog.view.close()
 
     async def exec_test():
-        await asyncio.sleep(1)
-        QTest.keyClicks(connection_config_dialog.view.edit_server, simple_fake_server.peer_doc().endpoints[0].ipv4)
-        connection_config_dialog.view.spinbox_port.setValue(simple_fake_server.peer_doc().endpoints[0].port)
-        assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_node
         QTest.mouseClick(connection_config_dialog.view.button_connect, Qt.LeftButton)
         await asyncio.sleep(1)
         assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_connection
@@ -122,10 +111,6 @@ async def test_connect_wrong_pubkey(application, simple_fake_server, wrong_bob_p
             connection_config_dialog.view.close()
 
     async def exec_test():
-        await asyncio.sleep(1)
-        QTest.keyClicks(connection_config_dialog.view.edit_server, simple_fake_server.peer_doc().endpoints[0].ipv4)
-        connection_config_dialog.view.spinbox_port.setValue(simple_fake_server.peer_doc().endpoints[0].port)
-        assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_node
         QTest.mouseClick(connection_config_dialog.view.button_connect, Qt.LeftButton)
         await asyncio.sleep(1)
         assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_connection
diff --git a/tests/technical/test_blockchain_service.py b/tests/technical/test_blockchain_service.py
index 2fa73fdd..22216985 100644
--- a/tests/technical/test_blockchain_service.py
+++ b/tests/technical/test_blockchain_service.py
@@ -5,15 +5,15 @@ import pytest
 
 @pytest.mark.asyncio
 async def test_new_block_with_ud(application_with_one_connection, fake_server):
-    previous_ud = application_with_one_connection.blockchain_services[fake_server.forge.currency].previous_ud()
+    previous_ud = application_with_one_connection.blockchain_service.previous_ud()
     fake_server.forge.forge_block()
     fake_server.forge.generate_dividend()
     fake_server.forge.forge_block()
     fake_server.forge.generate_dividend()
     fake_server.forge.forge_block()
     new_blocks = fake_server.forge.blocks[-3:]
-    application_with_one_connection.blockchain_services[fake_server.forge.currency].handle_new_blocks(
+    application_with_one_connection.blockchain_service.handle_new_blocks(
         new_blocks)
-    previous_ud_after_parse = application_with_one_connection.blockchain_services[fake_server.forge.currency].previous_ud()
+    previous_ud_after_parse = application_with_one_connection.blockchain_service.previous_ud()
     assert previous_ud_after_parse > previous_ud
     await fake_server.close()
\ No newline at end of file
diff --git a/tests/technical/test_identities_service.py b/tests/technical/test_identities_service.py
index ea63c1ac..72a17fed 100644
--- a/tests/technical/test_identities_service.py
+++ b/tests/technical/test_identities_service.py
@@ -5,7 +5,7 @@ import pytest
 
 @pytest.mark.asyncio
 async def test_new_block_with_certs(application_with_one_connection, fake_server, bob, alice):
-    certs_before_send = application_with_one_connection.identities_services[fake_server.forge.currency].certifications_sent(
+    certs_before_send = application_with_one_connection.identities_service.certifications_sent(
         bob.key.pubkey)
     alice_user_identity = fake_server.forge.user_identities[bob.key.pubkey]
     alice_identity = Identity(currency=fake_server.forge.currency,
@@ -16,7 +16,7 @@ async def test_new_block_with_certs(application_with_one_connection, fake_server
     bob_connection = application_with_one_connection.db.connections_repo.get_one(pubkey=bob.key.pubkey)
     await application_with_one_connection.documents_service.certify(bob_connection,
                                                                        bob.password, alice_identity)
-    certs_after_send = application_with_one_connection.identities_services[fake_server.forge.currency].certifications_sent(
+    certs_after_send = application_with_one_connection.identities_service.certifications_sent(
         bob.key.pubkey)
     assert len(certs_after_send) == len(certs_before_send) + 1
     assert certs_after_send[0].written_on == 0
@@ -25,9 +25,9 @@ async def test_new_block_with_certs(application_with_one_connection, fake_server
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     new_blocks = fake_server.forge.blocks[-3:]
-    await application_with_one_connection.identities_services[fake_server.forge.currency].handle_new_blocks(
+    await application_with_one_connection.identities_service.handle_new_blocks(
         new_blocks)
-    certs_after_parse = application_with_one_connection.identities_services[fake_server.forge.currency].certifications_sent(
+    certs_after_parse = application_with_one_connection.identities_service.certifications_sent(
         bob.key.pubkey)
     assert len(certs_after_parse) == len(certs_after_send)
     assert certs_after_parse[0].written_on == fake_server.forge.blocks[-3].number
diff --git a/tests/technical/test_transactions_service.py b/tests/technical/test_transactions_service.py
index 47bd10bd..0bb6740a 100644
--- a/tests/technical/test_transactions_service.py
+++ b/tests/technical/test_transactions_service.py
@@ -4,35 +4,35 @@ from sakia.data.entities import Transaction
 
 @pytest.mark.asyncio
 async def test_send_tx_then_validate(application_with_one_connection, fake_server, bob, alice):
-    tx_before_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    tx_before_send = application_with_one_connection.transactions_service.transfers(bob.key.pubkey)
     bob_connection = application_with_one_connection.db.connections_repo.get_one(pubkey=bob.key.pubkey)
     await application_with_one_connection.documents_service.send_money(bob_connection,
                                                                  bob.password,
                                                                  alice.key.pubkey, 10, 0, "Test comment")
-    tx_after_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    tx_after_send = application_with_one_connection.transactions_service.transfers(bob.key.pubkey)
     assert len(tx_before_send) + 1 == len(tx_after_send)
     assert tx_after_send[-1].state is Transaction.AWAITING
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     new_blocks = fake_server.forge.blocks[-3:]
-    await application_with_one_connection.transactions_services[fake_server.forge.currency].handle_new_blocks(new_blocks)
-    tx_after_parse = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    await application_with_one_connection.transactions_service.handle_new_blocks(new_blocks)
+    tx_after_parse = application_with_one_connection.transactions_service.transfers(bob.key.pubkey)
     assert tx_after_parse[-1].state is Transaction.VALIDATED
     await fake_server.close()
 
 
 @pytest.mark.asyncio
 async def test_receive_tx(application_with_one_connection, fake_server, bob, alice):
-    tx_before_send = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    tx_before_send = application_with_one_connection.transactions_service.transfers(bob.key.pubkey)
     fake_server.forge.push(alice.send_money(10, fake_server.forge.user_identities[alice.key.pubkey].sources, bob,
                                             fake_server.forge.blocks[-1].blockUID, "Test receive"))
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     new_blocks = fake_server.forge.blocks[-3:]
-    await application_with_one_connection.transactions_services[fake_server.forge.currency].handle_new_blocks(new_blocks)
-    tx_after_parse = application_with_one_connection.transactions_services[fake_server.forge.currency].transfers(bob.key.pubkey)
+    await application_with_one_connection.transactions_service.handle_new_blocks(new_blocks)
+    tx_after_parse = application_with_one_connection.transactions_service.transfers(bob.key.pubkey)
     assert tx_after_parse[-1].state is Transaction.VALIDATED
     assert len(tx_before_send) + 1 == len(tx_after_parse)
     await fake_server.close()
@@ -40,7 +40,7 @@ async def test_receive_tx(application_with_one_connection, fake_server, bob, ali
 
 @pytest.mark.asyncio
 async def test_issue_dividend(application_with_one_connection, fake_server, bob):
-    dividends_before_send = application_with_one_connection.transactions_services[fake_server.forge.currency].dividends(bob.key.pubkey)
+    dividends_before_send = application_with_one_connection.transactions_service.dividends(bob.key.pubkey)
     fake_server.forge.forge_block()
     fake_server.forge.generate_dividend()
     fake_server.forge.forge_block()
@@ -49,8 +49,8 @@ async def test_issue_dividend(application_with_one_connection, fake_server, bob)
     fake_server.forge.forge_block()
     fake_server.forge.forge_block()
     new_blocks = fake_server.forge.blocks[-5:]
-    await application_with_one_connection.transactions_services[fake_server.forge.currency].handle_new_blocks(new_blocks)
-    dividends_after_parse = application_with_one_connection.transactions_services[fake_server.forge.currency].dividends(bob.key.pubkey)
+    await application_with_one_connection.transactions_service.handle_new_blocks(new_blocks)
+    dividends_after_parse = application_with_one_connection.transactions_service.dividends(bob.key.pubkey)
     assert len(dividends_before_send) + 2 == len(dividends_after_parse)
     await fake_server.close()
 
-- 
GitLab