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