''' Created on 21 févr. 2015 @author: inso ''' from ucoinpy.documents.peer import Peer, BMAEndpoint, Endpoint from ucoinpy.api import bma from requests.exceptions import RequestException from ...core.person import Person from ...tools.exceptions import PersonNotFoundError import logging import time class Node(object): ''' classdocs ''' ONLINE = 1 OFFLINE = 2 DESYNCED = 3 CORRUPTED = 4 def __init__(self, endpoints, pubkey, block, state): ''' Constructor ''' self._endpoints = endpoints self._pubkey = pubkey self._block = block self._state = state @classmethod def from_peer(cls, currency, peer): node = cls(peer.endpoints, "", 0, Node.ONLINE) node.refresh_state(currency) return node @classmethod def from_json(cls, currency, data): endpoints = [] for endpoint_data in data['endpoints']: endpoints.append(Endpoint.from_inline(endpoint_data)) node = cls(endpoints, "", 0, Node.ONLINE) node.refresh_state(currency) return node @property def pubkey(self): return self._pubkey @property def endpoint(self): return next((e for e in self._endpoints if type(e) is BMAEndpoint)) @property def block(self): return self._block @property def state(self): return self._state def check_sync(self, currency, block): if self._block < block: self._state = Node.DESYNCED else: self._state = Node.ONLINE def refresh_state(self, currency): try: informations = bma.network.Peering(self.endpoint.conn_handler()).get() block = bma.blockchain.Current(self.endpoint.conn_handler()).get() block_number = block["number"] node_pubkey = informations["pubkey"] node_currency = informations["currency"] except ValueError as e: if '404' in e: block_number = 0 except RequestException: self._state = Node.OFFLINE if node_currency != currency: self.state = Node.CORRUPTED self._block = block_number self._pubkey = node_pubkey def peering_traversal(self, currency, found_nodes, traversed_pubkeys, interval): logging.debug("Read {0} peering".format(self.pubkey)) traversed_pubkeys.append(self.pubkey) self.refresh_state(currency) if self.pubkey not in [n.pubkey for n in found_nodes]: found_nodes.append(self) try: next_peers = bma.network.peering.Peers(self.endpoint.conn_handler()).get() for p in next_peers: next_peer = Peer.from_signed_raw("{0}{1}\n".format(p['value']['raw'], p['value']['signature'])) logging.debug(traversed_pubkeys) logging.debug("Traversing : next to read : {0} : {1}".format(next_peer.pubkey, (next_peer.pubkey not in traversed_pubkeys))) next_node = Node.from_peer(next_peer) if next_node.pubkey not in traversed_pubkeys: next_node.peering_traversal(currency, found_nodes, traversed_pubkeys) time.sleep(interval) except RequestException as e: self._state = Node.OFFLINE