Beispiel #1
0
    async def from_address(cls, currency, address, port):
        """
        Factory method to get a node from a given address

        :param str currency: The node currency. None if we don't know\
         the currency it should have, for example if its the first one we add
        :param str address: The node address
        :param int port: The node port
        :return: A new node
        :rtype: sakia.core.net.Node
        """
        peer_data = await bma.network.Peering(ConnectionHandler(address, port)).get()

        peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
                                                  peer_data['signature']))

        if currency is not None:
            if peer.currency != currency:
                raise InvalidNodeCurrency(peer.currency, currency)

        node = cls(peer,
                   "", peer.pubkey, None, Node.ONLINE, time.time(),
                   {'root': "", 'leaves': []}, "", "", 0)
        logging.debug("Node from address : {:}".format(str(node)))
        return node
Beispiel #2
0
    def peering_traversal(self, knew_pubkeys, found_nodes, traversed_pubkeys,
                          interval, continue_crawling):
        logging.debug("Read {0} peering".format(self.pubkey))
        traversed_pubkeys.append(self.pubkey)
        self.refresh_state()

        if self.pubkey not in [n.pubkey for n in found_nodes]:
            # if node is corrupted remove it
            if self.state != Node.CORRUPTED:
                logging.debug("Found : {0} node".format(self.pubkey))
                found_nodes.append(self)
            logging.debug(self.neighbours)
            for n in self.neighbours:
                try:
                    e = next(e for e in n if type(e) is BMAEndpoint)
                    peering = bma.network.Peering(e.conn_handler()).get()
                except:
                    continue
                peer = Peer.from_signed_raw("{0}{1}\n".format(
                    peering['raw'], peering['signature']))
                if peer.pubkey not in traversed_pubkeys and \
                    peer.pubkey not in knew_pubkeys and continue_crawling():
                    node = Node.from_peer(self._currency, peer)
                    logging.debug(traversed_pubkeys)
                    logging.debug(
                        "Traversing : next to read : {0} : {1}".format(
                            node.pubkey,
                            (node.pubkey not in traversed_pubkeys)))
                    node.peering_traversal(knew_pubkeys, found_nodes,
                                           traversed_pubkeys, interval,
                                           continue_crawling)
                    time.sleep(interval)
Beispiel #3
0
    def peering_traversal(self, knew_pubkeys, found_nodes,
                          traversed_pubkeys, interval,
                          continue_crawling):
        logging.debug("Read {0} peering".format(self.pubkey))
        traversed_pubkeys.append(self.pubkey)
        self.refresh_state()

        if self.pubkey not in [n.pubkey for n in found_nodes]:
            # if node is corrupted remove it
            if self.state != Node.CORRUPTED:
                logging.debug("Found : {0} node".format(self.pubkey))
                found_nodes.append(self)
            logging.debug(self.neighbours)
            for n in self.neighbours:
                try:
                    e = next(e for e in n if type(e) is BMAEndpoint)
                    peering = bma.network.Peering(e.conn_handler()).get()
                except:
                    continue
                peer = Peer.from_signed_raw("{0}{1}\n".format(peering['raw'],
                                                            peering['signature']))
                if peer.pubkey not in traversed_pubkeys and \
                    peer.pubkey not in knew_pubkeys and continue_crawling():
                    node = Node.from_peer(self._currency, peer)
                    logging.debug(traversed_pubkeys)
                    logging.debug("Traversing : next to read : {0} : {1}".format(node.pubkey,
                                  (node.pubkey not in traversed_pubkeys)))
                    node.peering_traversal(knew_pubkeys, found_nodes,
                                        traversed_pubkeys, interval, continue_crawling)
                    time.sleep(interval)
Beispiel #4
0
 def refresh_peer_data(self, peer_data):
     if "raw" in peer_data:
         try:
             str_doc = "{0}{1}\n".format(peer_data['raw'],
                                         peer_data['signature'])
             peer_doc = Peer.from_signed_raw(str_doc)
             pubkey = peer_data['pubkey']
             self.neighbour_found.emit(peer_doc, pubkey)
         except MalformedDocumentError as e:
             logging.debug(str(e))
     else:
         logging.debug("Incorrect leaf reply")
Beispiel #5
0
    async def refresh_informations(self):
        """
        Refresh basic information (pubkey and currency)
        """
        conn_handler = self.endpoint.conn_handler()

        try:
            peering_data = await bma.network.Peering(conn_handler).get()
            node_pubkey = peering_data["pubkey"]
            node_currency = peering_data["currency"]
            self.state = Node.ONLINE

            if peering_data['raw'] != self.peer.raw():
                peer = Peer.from_signed_raw("{0}{1}\n".format(peering_data['raw'], peering_data['signature']))
                if peer.blockid.number > peer.blockid.number:
                    self.peer = Peer.from_signed_raw("{0}{1}\n".format(peering_data['raw'], peering_data['signature']))

            if node_pubkey != self.pubkey:
                self._pubkey = node_pubkey
                self.identity_changed.emit()

            if node_currency != self.currency:
                self.state = Node.CORRUPTED
                logging.debug("Change : new state corrupted")
                self.changed.emit()

        except ValueError as e:
            logging.debug("Error in peering reply : {0}".format(str(e)))
            self.state = Node.OFFLINE
            self.changed.emit()
        except (ClientError, gaierror, TimeoutError, DisconnectedError) as e:
            logging.debug("{0} : {1}".format(type(e).__name__, self.pubkey[:5]))
            self.state = Node.OFFLINE
        except jsonschema.ValidationError as e:
            logging.debug(str(e))
            logging.debug("Validation error : {0}".format(self.pubkey[:5]))
            self.state = Node.CORRUPTED
Beispiel #6
0
    def refresh_peers(self):
        """
        Refresh the list of peers knew by this node
        """
        conn_handler = self.endpoint.conn_handler()

        try:
            peers_data = yield from bma.network.peering.Peers(conn_handler).get(leaves='true')
            self.state = Node.ONLINE
            if peers_data['root'] != self._last_merkle['root']:
                leaves = [leaf for leaf in peers_data['leaves']
                          if leaf not in self._last_merkle['leaves']]
                for leaf_hash in leaves:
                    try:
                        leaf_data = yield from bma.network.peering.Peers(conn_handler).get(leaf=leaf_hash)
                        if "raw" in leaf_data['leaf']['value']:
                            str_doc = "{0}{1}\n".format(leaf_data['leaf']['value']['raw'],
                                                                        leaf_data['leaf']['value']['signature'])
                            peer_doc = Peer.from_signed_raw(str_doc)
                            pubkey = leaf_data['leaf']['value']['pubkey']
                            self.neighbour_found.emit(peer_doc, pubkey)
                        else:
                            logging.debug("Incorrect leaf reply")
                    except (AttributeError, ValueError) as e:
                        logging.debug("{pubkey} : Incorrect peer data in {leaf}".format(pubkey=self.pubkey[:5],
                                                                                        leaf=leaf_hash))
                        self.state = Node.OFFLINE
                        self.changed.emit()
                    except (ClientError, gaierror, TimeoutError, DisconnectedError) as e:
                        logging.debug("{0} : {1}".format(type(e).__name__, self.pubkey))
                        self.state = Node.OFFLINE
                    except jsonschema.ValidationError:
                        logging.debug("Validation error : {0}".format(self.pubkey))
                        self.state = Node.CORRUPTED
                self._last_merkle = {'root' : peers_data['root'],
                                     'leaves': peers_data['leaves']}
        except ValueError as e:
            logging.debug("Error in peers reply")
            self.state = Node.OFFLINE
            self.changed.emit()
        except (ClientError, gaierror, TimeoutError, DisconnectedError) as e:
            logging.debug("{0} : {1}".format(type(e).__name__, self.pubkey))
            self.state = Node.OFFLINE
        except jsonschema.ValidationError:
            logging.debug("Validation error : {0}".format(self.pubkey))
            self.state = Node.CORRUPTED
Beispiel #7
0
    def from_address(cls, currency, address, port):
        '''
        Factory method to get a node from a given address

        :param str currency: The node currency. None if we don't know\
         the currency it should have, for example if its the first one we add
        :param str address: The node address
        :param int port: The node port
        '''
        peer_data = bma.network.Peering(ConnectionHandler(address, port)).get()

        peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
                                                  peer_data['signature']))

        if currency is not None:
            if peer.currency != currency:
                raise InvalidNodeCurrency(peer.currency, currency)

        node = cls(peer.currency, peer.endpoints, "", peer.pubkey, 0,
                   Node.ONLINE, time.time(), "", "")
        logging.debug("Node from address : {:}".format(str(node)))
        return node
Beispiel #8
0
    def from_address(cls, currency, address, port):
        '''
        Factory method to get a node from a given address

        :param str currency: The node currency. None if we don't know\
         the currency it should have, for example if its the first one we add
        :param str address: The node address
        :param int port: The node port
        '''
        peer_data = bma.network.Peering(ConnectionHandler(address, port)).get()

        peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
                                                      peer_data['signature']))

        if currency is not None:
            if peer.currency != currency:
                raise InvalidNodeCurrency(peer.currency, currency)

        node = cls(peer.currency, peer.endpoints, "", peer.pubkey, 0,
                   Node.ONLINE, time.time(), "", "")
        logging.debug("Node from address : {:}".format(str(node)))
        return node
Beispiel #9
0
    def setUp(self):
        self.setUpQuamash()
        QLocale.setDefault(QLocale("en_GB"))
        self.identities_registry = IdentitiesRegistry()

        self.application = Application(self.qapplication, self.lp, self.identities_registry)
        self.application.preferences['notifications'] = False

        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==
""")
        self.node = Node(self.peer,
                         "", "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk",
                         None, Node.ONLINE,
                         time.time(), {}, "ucoin", "0.12.0", 0)
        self.network = Network.create(self.node)
        self.bma_access = BmaAccess.create(self.network)
        self.community = Community("test_currency", self.network, self.bma_access)
Beispiel #10
0
    def from_json(cls, currency, data, file_version):
        """
        Loads a node from json data

        :param str currency: the currency of the community
        :param dict data: the json data of the node
        :param NormalizedVersion file_version: the version of the file
        :return: A new node
        :rtype: Node
        """
        endpoints = []
        uid = ""
        pubkey = ""
        software = ""
        version = ""
        fork_window = 0
        block = None
        last_change = time.time()
        state = Node.OFFLINE
        if 'uid' in data:
            uid = data['uid']

        if 'pubkey' in data:
            pubkey = data['pubkey']

        if 'last_change' in data:
            last_change = data['last_change']

        if 'block' in data:
            block = data['block']

        if 'state' in data:
            state = data['state']

        if 'software' in data:
            software = data['software']

        if 'version' in data:
            version = data['version']

        if 'fork_window' in data:
            fork_window = data['fork_window']

        if parse_version("0.11") <= file_version < parse_version("0.12dev1") :
            for endpoint_data in data['endpoints']:
                endpoints.append(Endpoint.from_inline(endpoint_data))

            if currency in data:
                currency = data['currency']

            peer = Peer("1", currency, pubkey, BlockId(0, Block.Empty_Hash), endpoints, "SOMEFAKESIGNATURE")
        else:
            peer = Peer.from_signed_raw(data['peer'])

        node = cls(peer, uid, pubkey, block,
                   state, last_change,
                   {'root': "", 'leaves': []},
                   software, version, fork_window)

        logging.debug("Node from json : {:}".format(str(node)))
        return node
Beispiel #11
0
    def refresh_state(self):
        logging.debug("Refresh state")
        emit_change = False
        try:
            informations = bma.network.Peering(self.endpoint.conn_handler()).get()
            node_pubkey = informations["pubkey"]
            try:
                block = bma.blockchain.Current(self.endpoint.conn_handler()).get()
                block_number = block["number"]
            except ValueError as e:
                if '404' in str(e):
                    block_number = 0

            peers_data = bma.network.peering.Peers(self.endpoint.conn_handler()).get()
            neighbours = []
            for p in peers_data:
                peer = Peer.from_signed_raw("{0}{1}\n".format(p['value']['raw'],
                                                            p['value']['signature']))
                neighbours.append(peer.endpoints)
            logging.debug("Found neighbours : {0}".format(len(neighbours)))

            node_currency = informations["currency"]
            node_uid = self._request_uid()

            implementation = bma.node.Summary(self.endpoint.conn_handler()).get()
            software = implementation["ucoin"]["software"]
            version = implementation["ucoin"]["version"]

            #If the nodes goes back online...
            if self.state in (Node.OFFLINE, Node.CORRUPTED):
                self.state = Node.ONLINE
                logging.debug("Change : new state online")
                emit_change = True
        except ConnectionError as e:
            logging.debug(str(e))

            if self.state != Node.OFFLINE:
                self.state = Node.OFFLINE
                logging.debug("Change : new state offine")
                emit_change = True
            # Dirty hack to reload resolv.conf on linux
            if 'Connection aborted' in str(e) and 'gaierror' in str(e):
                logging.debug("Connection Aborted")
                if 'linux' in sys.platform:
                    try:
                        libc = ctypes.CDLL('libc.so.6')
                        res_init = getattr(libc, '__res_init')
                        res_init(None)
                    except:
                        logging.error('Error calling libc.__res_init')
        except RequestException as e:
            logging.debug(str(e))
            if self.state != Node.OFFLINE:
                self.state = Node.OFFLINE
                logging.debug("Change : new state offine")
                emit_change = True

        # If not is offline, do not refresh last data
        if self.state != Node.OFFLINE:
            # If not changed its currency, consider it corrupted
            if node_currency != self._currency:
                self.state = Node.CORRUPTED
                logging.debug("Change : new state corrupted")
                emit_change = True
            else:
                if block_number != self.block:
                    logging.debug("Change : new block {0} -> {1}".format(self.block,
                                                                         block_number))
                    self.block = block_number
                    logging.debug("Changed block {0} -> {1}".format(self.block,
                                                                         block_number))
                    emit_change = True

                if node_pubkey != self._pubkey:
                    logging.debug("Change : new pubkey {0} -> {1}".format(self._pubkey,
                                                                          node_pubkey))
                    self._pubkey = node_pubkey
                    emit_change = True

                if node_uid != self._uid:
                    logging.debug("Change : new uid")
                    self._uid = node_uid
                    emit_change = True

                if software != self._software:
                    logging.debug("Change : new software")
                    self._software = software
                    emit_change = True

                if version != self._version:
                    logging.debug("Change : new version")
                    self._version = version
                    emit_change = True

                logging.debug(neighbours)
                new_inlines = [e.inline() for n in neighbours for e in n]
                last_inlines = [e.inline() for n in self._neighbours for e in n]

                hash_new_neighbours = hash(tuple(frozenset(sorted(new_inlines))))
                hash_last_neighbours = hash(tuple(frozenset(sorted(last_inlines))))
                if hash_new_neighbours != hash_last_neighbours:
                    self._neighbours = neighbours
                    logging.debug("Change : new neighbours {0} -> {1}".format(last_inlines,
                                                                              new_inlines))
                    emit_change = True

        if emit_change:
            self.changed.emit()
Beispiel #12
0
    def refresh_state(self):
        logging.debug("Refresh state")
        emit_change = False
        try:
            informations = bma.network.Peering(
                self.endpoint.conn_handler()).get()
            node_pubkey = informations["pubkey"]
            try:
                block = bma.blockchain.Current(
                    self.endpoint.conn_handler()).get()
                block_number = block["number"]
            except ValueError as e:
                if '404' in str(e):
                    block_number = 0

            peers_data = bma.network.peering.Peers(
                self.endpoint.conn_handler()).get()
            neighbours = []
            for p in peers_data:
                peer = Peer.from_signed_raw("{0}{1}\n".format(
                    p['value']['raw'], p['value']['signature']))
                neighbours.append(peer.endpoints)
            logging.debug("Found neighbours : {0}".format(len(neighbours)))

            node_currency = informations["currency"]
            node_uid = self._request_uid()

            implementation = bma.node.Summary(
                self.endpoint.conn_handler()).get()
            software = implementation["ucoin"]["software"]
            version = implementation["ucoin"]["version"]

            #If the nodes goes back online...
            if self.state in (Node.OFFLINE, Node.CORRUPTED):
                self.state = Node.ONLINE
                logging.debug("Change : new state online")
                emit_change = True
        except ConnectionError as e:
            logging.debug(str(e))

            if self.state != Node.OFFLINE:
                self.state = Node.OFFLINE
                logging.debug("Change : new state offine")
                emit_change = True
            # Dirty hack to reload resolv.conf on linux
            if 'Connection aborted' in str(e) and 'gaierror' in str(e):
                logging.debug("Connection Aborted")
                if 'linux' in sys.platform:
                    try:
                        libc = ctypes.CDLL('libc.so.6')
                        res_init = getattr(libc, '__res_init')
                        res_init(None)
                    except:
                        logging.error('Error calling libc.__res_init')
        except RequestException as e:
            logging.debug(str(e))
            if self.state != Node.OFFLINE:
                self.state = Node.OFFLINE
                logging.debug("Change : new state offine")
                emit_change = True

        # If not is offline, do not refresh last data
        if self.state != Node.OFFLINE:
            # If not changed its currency, consider it corrupted
            if node_currency != self._currency:
                self.state = Node.CORRUPTED
                logging.debug("Change : new state corrupted")
                emit_change = True
            else:
                if block_number != self.block:
                    logging.debug("Change : new block {0} -> {1}".format(
                        self.block, block_number))
                    self.block = block_number
                    logging.debug("Changed block {0} -> {1}".format(
                        self.block, block_number))
                    emit_change = True

                if node_pubkey != self._pubkey:
                    logging.debug("Change : new pubkey {0} -> {1}".format(
                        self._pubkey, node_pubkey))
                    self._pubkey = node_pubkey
                    emit_change = True

                if node_uid != self._uid:
                    logging.debug("Change : new uid")
                    self._uid = node_uid
                    emit_change = True

                if software != self._software:
                    logging.debug("Change : new software")
                    self._software = software
                    emit_change = True

                if version != self._version:
                    logging.debug("Change : new version")
                    self._version = version
                    emit_change = True

                logging.debug(neighbours)
                new_inlines = [e.inline() for n in neighbours for e in n]
                last_inlines = [
                    e.inline() for n in self._neighbours for e in n
                ]

                hash_new_neighbours = hash(
                    tuple(frozenset(sorted(new_inlines))))
                hash_last_neighbours = hash(
                    tuple(frozenset(sorted(last_inlines))))
                if hash_new_neighbours != hash_last_neighbours:
                    self._neighbours = neighbours
                    logging.debug("Change : new neighbours {0} -> {1}".format(
                        last_inlines, new_inlines))
                    emit_change = True

        if emit_change:
            self.changed.emit()