diff --git a/src/sakia/__init__.py b/src/sakia/__init__.py index 993750a514d8123b5e23027dc8e44da36df81c60..d4c85e473175c7b0fccd54e9748b783ab229ab3d 100644 --- a/src/sakia/__init__.py +++ b/src/sakia/__init__.py @@ -1,2 +1,2 @@ -__version_info__ = ('0', '11', '5') +__version_info__ = ('0', '12', '0') __version__ = '.'.join(__version_info__) diff --git a/src/sakia/core/account.py b/src/sakia/core/account.py index 820f0604fdb6807512580d4f73a3e7e29e6c7fc4..90caa204bc15ab779aa6c2994a863ea08c7559c9 100644 --- a/src/sakia/core/account.py +++ b/src/sakia/core/account.py @@ -20,6 +20,7 @@ from .wallet import Wallet from .community import Community from .registry import LocalState from ..tools.exceptions import ContactAlreadyExists +from .. import __version__ from ucoinpy.api import bma from ucoinpy.api.bma import PROTOCOL_VERSION from aiohttp.errors import ClientError @@ -103,10 +104,10 @@ class Account(QObject): """ salt = json_data['salt'] pubkey = json_data['pubkey'] - if 'version' in json_data: - version = StrictVersion(json_data['version']) + if 'file_version' in json_data: + file_version = StrictVersion(json_data['file_version']) else: - version = StrictVersion('0.11.5') + file_version = StrictVersion('0.11.5') name = json_data['name'] contacts = [] @@ -120,7 +121,7 @@ class Account(QObject): communities = [] for data in json_data['communities']: - community = Community.load(data, version) + community = Community.load(data, file_version) communities.append(community) account = cls(salt, pubkey, name, communities, wallets, @@ -582,5 +583,6 @@ class Account(QObject): 'pubkey': self.pubkey, 'communities': data_communities, 'wallets': data_wallets, - 'contacts': self.contacts} + 'contacts': self.contacts, + 'file_version': __version__} return data diff --git a/src/sakia/core/community.py b/src/sakia/core/community.py index 2a368bc34f373928dd0ec1cf6a24b72b5046550d..cbc86b64e31cc79f449a7aa8ecd38924a411ccc6 100644 --- a/src/sakia/core/community.py +++ b/src/sakia/core/community.py @@ -57,15 +57,15 @@ class Community(QObject): return community @classmethod - def load(cls, json_data, version): + def load(cls, json_data, file_version): """ Load a community from json :param dict json_data: The community as a dict in json format - :param distutils.version.StrictVersion version: the file sakia version + :param distutils.version.StrictVersion file_version: the file sakia version """ currency = json_data['currency'] - network = Network.from_json(currency, json_data['peers'], version) + network = Network.from_json(currency, json_data['peers'], file_version) bma_access = BmaAccess.create(network) community = cls(currency, network, bma_access) return community diff --git a/src/sakia/core/net/network.py b/src/sakia/core/net/network.py index 4ca3232790e201a55d7be4ade121a27856574e4a..4ba45bff087dddbe73a8d167f7854003cf43e1d9 100644 --- a/src/sakia/core/net/network.py +++ b/src/sakia/core/net/network.py @@ -88,17 +88,17 @@ class Network(QObject): other_node.state = node.state @classmethod - def from_json(cls, currency, json_data, version): + def from_json(cls, currency, json_data, file_version): """ Load a network from a configured community :param str currency: The currency name of a community :param dict json_data: A json_data view of a network - :param distutils.version.StrictVersion version: the version of the json file + :param distutils.version.StrictVersion file_version: the version of the json file """ nodes = [] for data in json_data: - node = Node.from_json(currency, data, version) + node = Node.from_json(currency, data, file_version) nodes.append(node) network = cls(currency, nodes) return network @@ -345,6 +345,8 @@ class Network(QObject): logging.debug(str(e)) else: node = [n for n in self.nodes if n.pubkey == pubkey][0] + if BlockId.from_str(node.peer.blockid).number < BlockId.from_str(peer.blockid).number: + node.peer = peer @pyqtSlot() def handle_identity_change(self): diff --git a/src/sakia/core/net/node.py b/src/sakia/core/net/node.py index 1b2a834198de2e0158967af4c055a412170e0c54..39505e1cb0d091554667579e7927f27d4366e123 100644 --- a/src/sakia/core/net/node.py +++ b/src/sakia/core/net/node.py @@ -5,7 +5,7 @@ Created on 21 févr. 2015 """ from ucoinpy.documents.peer import Peer, Endpoint, BMAEndpoint -from ucoinpy.documents import Block +from ucoinpy.documents import Block, BlockId from ...tools.exceptions import InvalidNodeCurrency from ...tools.decorators import asyncify from ucoinpy.api import bma as bma @@ -163,7 +163,7 @@ class Node(QObject): if currency in data: currency = data['currency'] - peer = Peer("1", currency, pubkey, "0-{0}".format(Block.Empty_Hash), endpoints, "SOMEFAKESIGNATURE") + peer = Peer("1", currency, pubkey, BlockId(0, Block.Empty_Hash), endpoints, "SOMEFAKESIGNATURE") else: if 'peer' in data: peer = Peer.from_signed_raw(data['peer']) @@ -180,7 +180,6 @@ class Node(QObject): logging.debug("Saving root node : {:}".format(str(self))) data = {'pubkey': self._pubkey, 'uid': self._uid, - 'currency': self._currency, 'peer': self._peer.signed_raw()} return data @@ -241,6 +240,12 @@ class Node(QObject): def peer(self): return self._peer + @peer.setter + def peer(self, new_peer): + if self._peer != new_peer: + self._peer = new_peer + self.changed.emit() + @software.setter def software(self, new_soft): if self._software != new_soft: diff --git a/src/sakia/tests/unit/core/test_node.py b/src/sakia/tests/unit/core/test_node.py new file mode 100644 index 0000000000000000000000000000000000000000..e8d03e274d1be447f49696aaacf8b7f12faf937b --- /dev/null +++ b/src/sakia/tests/unit/core/test_node.py @@ -0,0 +1,122 @@ +import unittest +from asynctest import CoroutineMock, patch +from ucoinpy.documents import Peer, BlockId +from PyQt5.QtCore import QLocale +from sakia.core.net import Node +from sakia.tests import QuamashTest +from sakia.tests.mocks.bma import nice_blockchain +from distutils.version import StrictVersion + + +class TestNode(unittest.TestCase, QuamashTest): + def setUp(self): + self.setUpQuamash() + QLocale.setDefault(QLocale("en_GB")) + + def tearDown(self): + self.tearDownQuamash() + + def test_from_peer(self): + peer = Peer.from_signed_raw("""Version: 1 +Type: Peer +Currency: meta_brouzouf +PublicKey: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU +Block: 48698-000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8 +Endpoints: +BASIC_MERKLED_API ucoin.inso.ovh 80 +82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw== +""") + node = Node.from_peer('meta_brouzouf', peer, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(node.pubkey, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(node.endpoint.inline(), "BASIC_MERKLED_API ucoin.inso.ovh 80") + self.assertEqual(node.currency, "meta_brouzouf") + + @patch('ucoinpy.api.bma.network.Peering') + def test_from_address(self, peering): + peering.return_value.get = CoroutineMock(return_value={ + "version": 1, + "currency": "meta_brouzouf", + "endpoints": [ + "BASIC_MERKLED_API ucoin.inso.ovh 80" + ], + "block": "48698-000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8", + "signature": "82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw==", + "raw": "Version: 1\nType: Peer\nCurrency: meta_brouzouf\nPublicKey: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU\nBlock: 48698-000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8\nEndpoints:\nBASIC_MERKLED_API ucoin.inso.ovh 80\n", + "pubkey": "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU" + }) + + async def exec_test(): + node = await Node.from_address("meta_brouzouf", "127.0.0.1", 9000) + self.assertEqual(node.pubkey, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(node.endpoint.inline(), "BASIC_MERKLED_API ucoin.inso.ovh 80") + self.assertEqual(node.currency, "meta_brouzouf") + + self.lp.run_until_complete(exec_test()) + + def test_from_json_011(self): + json_data = {"version": "0.12.0", "state": 1, "fork_window": 0, "uid": "cgeek", + "block": nice_blockchain.bma_blockchain_current, + "endpoints": ["BASIC_MERKLED_API metab.ucoin.io 88.174.120.187 9201"], + "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk", + "last_change": 1448199706.6561477, "currency": "meta_brouzouf", "sofware": "ucoin"} + node = Node.from_json("meta_brouzouf", json_data, StrictVersion('0.11.5')) + self.assertEqual(node.version, "0.12.0") + self.assertEqual(node.state, 1) + self.assertEqual(node.fork_window, 0) + self.assertEqual(node.uid, "cgeek") + self.assertEqual(node.block, nice_blockchain.bma_blockchain_current) + self.assertEqual(node.endpoint.inline(), "BASIC_MERKLED_API metab.ucoin.io 88.174.120.187 9201") + self.assertEqual(node.pubkey, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk") + self.assertEqual(node.last_change, 1448199706.6561477) + self.assertEqual(node.currency, "meta_brouzouf") + self.assertEqual(node.peer.pubkey, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk") + self.assertEqual(node.peer.blockid.number, 0) + + def test_from_json_to_json(self): + json_data = {"version": "0.12.0", "state": 1, "fork_window": 0, "uid": "inso", + "block": nice_blockchain.bma_blockchain_current, + "peer": """Version: 1 +Type: Peer +Currency: meta_brouzouf +PublicKey: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU +Block: 48698-000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8 +Endpoints: +BASIC_MERKLED_API ucoin.inso.ovh 80 +82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw== +""", + "pubkey": "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU", + "last_change": 1448199706.6561477, "software": "ucoin"} + node = Node.from_json("meta_brouzouf", json_data, StrictVersion('0.12.0')) + self.assertEqual(node.version, "0.12.0") + self.assertEqual(node.state, 1) + self.assertEqual(node.fork_window, 0) + self.assertEqual(node.uid, "inso") + self.assertEqual(node.block, nice_blockchain.bma_blockchain_current) + self.assertEqual(node.endpoint.inline(), "BASIC_MERKLED_API ucoin.inso.ovh 80") + self.assertEqual(node.pubkey, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(node.last_change, 1448199706.6561477) + self.assertEqual(node.currency, "meta_brouzouf") + self.assertEqual(node.peer.pubkey, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(BlockId.from_str(node.peer.blockid).number, 48698) + self.assertEqual(BlockId.from_str(node.peer.blockid).sha_hash, "000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8") + + result = node.jsonify() + for key in result: + self.assertEqual(result[key], json_data[key], "Error with key {0}".format(key)) + + def test_jsonify_root_node(self): + peer = Peer.from_signed_raw("""Version: 1 +Type: Peer +Currency: meta_brouzouf +PublicKey: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU +Block: 48698-000005E0F228038E4DDD4F6CA4ACB01EC88FBAF8 +Endpoints: +BASIC_MERKLED_API ucoin.inso.ovh 80 +82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw== +""") + node = Node(peer, "inso", "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU", nice_blockchain.bma_blockchain_current, + Node.ONLINE, 1111111111, {}, "ucoin", "0.12", 0) + result = node.jsonify_root_node() + self.assertEqual(result['pubkey'], "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU") + self.assertEqual(result['uid'], "inso") + self.assertEqual(result['peer'], peer.signed_raw()) \ No newline at end of file