diff --git a/src/cutecoin/core/account.py b/src/cutecoin/core/account.py index 3bed754614232dc2323ecf20e11df2a54362663a..174ebcb777f9cb50e25f91cd2a1b334f5e6ac1ce 100644 --- a/src/cutecoin/core/account.py +++ b/src/cutecoin/core/account.py @@ -11,10 +11,8 @@ from ucoinpy.documents.peer import Peer from ucoinpy.documents.certification import SelfCertification, Certification from ucoinpy.documents.membership import Membership from ucoinpy.key import SigningKey -from ..tools.exceptions import PersonNotFoundError import logging -import hashlib import time from .wallet import Wallet @@ -113,17 +111,11 @@ class Account(object): def certify(self, password, community, pubkey): certified = Person.lookup(pubkey, community) - try: - block = community.get_block() - block_hash = hashlib.sha1(block.signed_raw().encode("ascii")).hexdigest().upper() - block_number = block['number'] - except ValueError as e: - block_number = 0 - block_hash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" + blockid = community.current_blockid() certification = Certification(PROTOCOL_VERSION, community.currency, self.pubkey, certified.pubkey, - block_hash, block_number, None) + blockid['number'], blockid['hash'], None) selfcert = certified.selfcert(community) logging.debug("SelfCertification : {0}".format(selfcert.raw())) @@ -201,20 +193,12 @@ class Account(object): 'other': []}) def send_membership(self, password, community, type): - self_ = Person.lookup(self.pubkey, community) - selfcert = self_.selfcert(community) - - try: - block = community.get_block() - block_hash = hashlib.sha1(block.signed_raw().encode("ascii")).hexdigest().upper() - block_number = block.number - except ValueError as e: - block_number = 0 - block_hash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" + selfcert = Person.lookup(self.pubkey, community) + blockid = community.current_blockid() membership = Membership(PROTOCOL_VERSION, community.currency, - selfcert.pubkey, block_number, - block_hash, type, selfcert.uid, + selfcert.pubkey, blockid['number'], + blockid['hash'], type, selfcert.uid, selfcert.timestamp, None) key = SigningKey(self.salt, password) membership.sign([key]) diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py index b1fce9fd625d38117c8a79ac192944cb1dfef7cc..4b831ac1ceba67e19841de7231966ce622d60b48 100644 --- a/src/cutecoin/core/community.py +++ b/src/cutecoin/core/community.py @@ -12,6 +12,7 @@ from ..tools.exceptions import NoPeerAvailable import logging import time import inspect +import hashlib class Community(object): @@ -97,6 +98,20 @@ class Community(object): return Block.from_signed_raw("{0}{1}\n".format(data['raw'], data['signature'])) + def current_blockid(self): + try: + block = self.request(bma.blockchain.Current, cached=False) + signed_raw = "{0}{1}\n".format(block['raw'], block['signature']) + block_hash = hashlib.sha1(signed_raw.encode("ascii")).hexdigest().upper() + block_number = block['number'] + except ValueError as e: + if '404' in str(e): + block_number = 0 + block_hash = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" + else: + raise + return {'number': block_number, 'hash': block_hash} + def members_pubkeys(self): ''' Listing members pubkeys of a community @@ -108,62 +123,71 @@ class Community(object): members.append(m['pubkey']) return members - def check_current_block(self, endpoint): + def _check_current_block(self, endpoint): if self.last_block is None: - peering = bma.network.Peering(endpoint.conn_handler()).get() - block_number = peering['block'].split('-')[0] + blockid = self.current_blockid() self.last_block = {"request_ts": time.time(), - "number": block_number} + "number": blockid['number']} elif self.last_block["request_ts"] + 60 < time.time(): - logging.debug("{0} > {1}".format(self.last_block["request_ts"] + 60, time.time())) self.last_block["request_ts"] = time.time() - peering = bma.network.Peering(endpoint.conn_handler()).get() - block_number = peering['block'].split('-')[0] - if block_number > self.last_block['number']: - self.last_block["number"] = block_number + blockid = self.current_blockid() + if blockid['number'] > self.last_block['number']: + self.last_block["number"] = blockid['number'] self.requests_cache = {} - def request(self, request, req_args={}, get_args={}, cached=True): + def _cached_request(self, request, req_args={}, get_args={}): for peer in self.peers: e = next(e for e in peer.endpoints if type(e) is BMAEndpoint) - self.check_current_block(e) - if cached and self.last_block["number"] != 0: + self._check_current_block(e) + try: + # We request the current block every five minutes + # If a new block is mined we reset the cache + cache_key = (hash(request), + hash(tuple(frozenset(sorted(req_args.keys())))), + hash(tuple(frozenset(sorted(req_args.items())))), + hash(tuple(frozenset(sorted(get_args.keys())))), + hash(tuple(frozenset(sorted(get_args.items()))))) + + if cache_key not in self.requests_cache.keys(): + if e.server: + logging.debug("Connecting to {0}:{1}".format(e.server, + e.port)) + else: + logging.debug("Connecting to {0}:{1}".format(e.ipv4, + e.port)) + + req = request(e.conn_handler(), **req_args) + data = req.get(**get_args) + if inspect.isgenerator(data): + cached_data = [] + for d in data: + cached_data.append(d) + self.requests_cache[cache_key] = cached_data + else: + self.requests_cache[cache_key] = data + except ValueError as e: + if '502' in str(e): + continue + else: + raise + return self.requests_cache[cache_key] + raise NoPeerAvailable(self.currency) + + def request(self, request, req_args={}, get_args={}, cached=True): + if cached: + return self._cached_request(request, req_args, get_args) + else: + for peer in self.peers: + e = next(e for e in peer.endpoints if type(e) is BMAEndpoint) try: - # We request the current block every five minutes - # If a new block is mined we reset the cache - cache_key = (hash(request), - hash(tuple(frozenset(sorted(req_args.keys())))), - hash(tuple(frozenset(sorted(req_args.items())))), - hash(tuple(frozenset(sorted(get_args.keys())))), - hash(tuple(frozenset(sorted(get_args.items()))))) - - if cache_key not in self.requests_cache.keys(): - if e.server: - logging.debug("Connecting to {0}:{1}".format(e.server, - e.port)) - else: - logging.debug("Connecting to {0}:{1}".format(e.ipv4, - e.port)) - - req = request(e.conn_handler(), **req_args) - data = req.get(**get_args) - if inspect.isgenerator(data): - cached_data = [] - for d in data: - cached_data.append(d) - self.requests_cache[cache_key] = cached_data - else: - self.requests_cache[cache_key] = data + req = request(e.conn_handler(), **req_args) + data = req.get(**get_args) + return data except ValueError as e: if '502' in str(e): continue else: raise - return self.requests_cache[cache_key] - else: - req = request(e.conn_handler(), **req_args) - data = req.get(**get_args) - return data raise NoPeerAvailable(self.currency) def post(self, request, req_args={}, post_args={}): diff --git a/src/cutecoin/gui/currency_tab.py b/src/cutecoin/gui/currency_tab.py index bab2a6672d33f81b395bf49d9396176e5871f23b..b4dce1e8b80d68d2a2b3405f8b311d906a86f7a2 100644 --- a/src/cutecoin/gui/currency_tab.py +++ b/src/cutecoin/gui/currency_tab.py @@ -25,15 +25,15 @@ class BlockchainWatcher(QObject): self.account = account self.community = community self.exiting = False - peering = self.community.request(bma.network.Peering) - self.last_block = peering['block'].split('-')[0] + blockid = self.community.current_blockid() + self.last_block = blockid['number'] @pyqtSlot() def watch(self): while not self.exiting: time.sleep(10) - peering = self.community.request(bma.network.Peering) - block_number = peering['block'].split('-')[0] + blockid = self.community.current_blockid() + block_number = blockid['number'] if self.last_block != block_number: for w in self.account.wallets: w.cache.refresh(self.community) @@ -92,8 +92,8 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget): self.tabs_account.addTab(self.tab_community, QIcon(':/icons/community_icon'), "Community") - peering = self.community.request(bma.network.Peering) - block_number = peering['block'].split('-')[0] + blockid = self.community.current_blockid() + block_number = blockid['number'] self.status_label.setText("Connected : Block {0}" .format(block_number)) @@ -170,8 +170,8 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget): self.app.save(self.app.current_account) def showEvent(self, event): - peering = self.community.request(bma.network.Peering) - block_number = peering['block'].split('-')[0] + blockid = self.community.current_blockid() + block_number = blockid['number'] self.status_label.setText("Connected : Block {0}" .format(block_number))