Example #1
0
 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
Example #2
0
    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']))
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
    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)