def _get_block_doc(self, community, number): """ Retrieve the current block document :param sakia.core.Community community: The community we look for a block :param int number: The block number to retrieve :return: the block doc or None if no block was found """ tries = 0 block_doc = None block = None while block is None and tries < 3: try: block = yield from community.bma_access.future_request(bma.blockchain.Block, req_args={'number': number}) signed_raw = "{0}{1}\n".format(block['raw'], block['signature']) try: block_doc = Block.from_signed_raw(signed_raw) except TypeError: logging.debug("Error in {0}".format(number)) block = None tries += 1 except ValueError as e: if '404' in str(e): block = None tries += 1 return block_doc
def get_block(self, number=None): ''' Get a block :param int number: The block number. If none, returns current block. ''' if number is None: data = self.request(bma.blockchain.Current) else: logging.debug("Requesting block {0}".format(number)) data = self.request(bma.blockchain.Block, req_args={'number': number}) return Block.from_signed_raw("{0}{1}\n".format(data['raw'], data['signature']))
def _parse_block(self, community, block_number, received_list): block = community.request(bma.blockchain.Block, req_args={'number': block_number}) signed_raw = "{0}{1}\n".format(block['raw'], block['signature']) try: block_doc = Block.from_signed_raw(signed_raw) except: logging.debug("Error in {0}".format(block_number)) raise for (txid, tx) in enumerate(block_doc.transactions): self._parse_transaction(community, tx, block_number, block_doc.mediantime, received_list, txid) logging.debug("Received {0} transactions".format(len(received_list))) awaiting = [t for t in self._transfers if t.state == Transfer.AWAITING] # After we checked all transactions, we check if # sent transactions still waiting for validation # have to be considered refused for transfer in awaiting: transfer.check_registered(tx, block_number, block_doc.mediantime)
def _refresh(self, community, block_number_from, block_to, received_list): """ Refresh last transactions :param sakia.core.Community community: The community :param list received_list: List of transactions received """ new_transfers = [] new_dividends = [] try: logging.debug("Refresh from : {0} to {1}".format(block_number_from, block_to['number'])) dividends = yield from self.request_dividends(community, block_number_from) with_tx_data = yield from community.bma_access.future_request(bma.blockchain.TX) members_pubkeys = yield from community.members_pubkeys() fork_window = community.network.fork_window(members_pubkeys) blocks_with_tx = with_tx_data['result']['blocks'] while block_number_from <= block_to['number']: udid = 0 for d in [ud for ud in dividends if ud['block_number'] == block_number_from]: state = TransferState.VALIDATED if block_number_from + fork_window <= block_to['number'] \ else TransferState.VALIDATING if d['block_number'] not in [ud['block_number'] for ud in self._dividends]: d['id'] = udid d['state'] = state new_dividends.append(d) udid += 1 else: known_dividend = [ud for ud in self._dividends if ud['block_number'] == d['block_number']][0] known_dividend['state'] = state # We parse only blocks with transactions if block_number_from in blocks_with_tx: transfers = yield from self._parse_block(community, block_number_from, received_list, udid + len(new_transfers)) new_transfers += transfers self.wallet.refresh_progressed.emit(block_number_from, block_to['number'], self.wallet.pubkey) block_number_from += 1 signed_raw = "{0}{1}\n".format(block_to['raw'], block_to['signature']) block_to = Block.from_signed_raw(signed_raw) for transfer in [t for t in self._transfers + new_transfers if t.state == TransferState.VALIDATING]: transfer.run_state_transitions((False, block_to, fork_window)) # We check if latest parsed block_number is a new high number if block_number_from > self.latest_block: self.available_sources = yield from self.wallet.sources(community) if self._stop_coroutines: return self.latest_block = block_number_from parameters = yield from community.parameters() for transfer in [t for t in self._transfers if t.state == TransferState.AWAITING]: transfer.run_state_transitions((False, block_to, parameters['avgGenTime'], parameters['medianTimeBlocks'])) except NoPeerAvailable as e: logging.debug(str(e)) self.wallet.refresh_finished.emit([]) return self._transfers = self._transfers + new_transfers self._dividends = self._dividends + new_dividends self.wallet.refresh_finished.emit(received_list)