Example #1
0
    def prepare_tx(self, key, receiver, blockstamp, amount, amount_base, message, currency):
        """
        Prepare a simple Transaction document
        :param SigningKey key: the issuer of the transaction
        :param str receiver: the target of the transaction
        :param duniterpy.documents.BlockUID blockstamp: the blockstamp
        :param int amount: the amount sent to the receiver
        :param int amount_base: the amount base of the currency
        :param str message: the comment of the tx
        :param str currency: the target community
        :return: the transaction document
        :rtype: List[sakia.data.entities.Transaction]
        """
        forged_tx = []
        sources = [None]*41
        while len(sources) > 40:
            result = self.tx_sources(int(amount), amount_base, currency, key.pubkey)
            sources = result[0]
            computed_outputs = result[1]
            overheads = result[2]
            # Fix issue #594
            if len(sources) > 40:
                sources_value = 0
                for s in sources[:39]:
                    sources_value += s.amount * (10**s.base)
                sources_value, sources_base = reduce_base(sources_value, 0)
                chained_tx = self.prepare_tx(key, key.pubkey, blockstamp,
                                             sources_value, sources_base, "[CHAINED]", currency)
                forged_tx += chained_tx
        self._sources_processor.consume(sources)
        logging.debug("Inputs : {0}".format(sources))

        inputs = self.tx_inputs(sources)
        unlocks = self.tx_unlocks(sources)
        outputs = self.tx_outputs(key.pubkey, receiver, computed_outputs, overheads)
        logging.debug("Outputs : {0}".format(outputs))
        txdoc = TransactionDoc(10, currency, blockstamp, 0,
                               [key.pubkey], inputs, unlocks,
                               outputs, message, None)
        txdoc.sign([key])
        self.commit_outputs_to_self(currency, key.pubkey, txdoc)
        time = self._blockchain_processor.time(currency)
        tx = Transaction(currency=currency,
                         pubkey=key.pubkey,
                         sha_hash=txdoc.sha_hash,
                         written_block=0,
                         blockstamp=blockstamp,
                         timestamp=time,
                         signatures=txdoc.signatures,
                         issuers=[key.pubkey],
                         receivers=[receiver],
                         amount=amount,
                         amount_base=amount_base,
                         comment=txdoc.comment,
                         txid=0,
                         state=Transaction.TO_SEND,
                         local=True,
                         raw=txdoc.signed_raw())
        forged_tx.append(tx)
        return forged_tx
Example #2
0
    def prepare_tx(self, key, receiver, blockstamp, amount, amount_base, message, currency):
        """
        Prepare a simple Transaction document
        :param SigningKey key: the issuer of the transaction
        :param str receiver: the target of the transaction
        :param duniterpy.documents.BlockUID blockstamp: the blockstamp
        :param int amount: the amount sent to the receiver
        :param int amount_base: the amount base of the currency
        :param str message: the comment of the tx
        :param str currency: the target community
        :return: the transaction document
        :rtype: List[sakia.data.entities.Transaction]
        """
        forged_tx = []
        sources = [None]*41
        while len(sources) > 40:
            result = self.tx_sources(int(amount), amount_base, currency, key.pubkey)
            sources = result[0]
            computed_outputs = result[1]
            overheads = result[2]
            # Fix issue #594
            if len(sources) > 40:
                sources_value = 0
                for s in sources[:39]:
                    sources_value += s.amount * (10**s.base)
                sources_value, sources_base = reduce_base(sources_value, 0)
                chained_tx = self.prepare_tx(key, key.pubkey, blockstamp,
                                             sources_value, sources_base, "[CHAINED]", currency)
                forged_tx += chained_tx
        self._sources_processor.consume(sources)
        logging.debug("Inputs : {0}".format(sources))

        inputs = self.tx_inputs(sources)
        unlocks = self.tx_unlocks(sources)
        outputs = self.tx_outputs(key.pubkey, receiver, computed_outputs, overheads)
        logging.debug("Outputs : {0}".format(outputs))
        txdoc = TransactionDoc(10, currency, blockstamp, 0,
                               [key.pubkey], inputs, unlocks,
                               outputs, message, None)
        txdoc.sign([key])
        self.commit_outputs_to_self(currency, key.pubkey, txdoc)
        time = self._blockchain_processor.time(currency)
        tx = Transaction(currency=currency,
                         pubkey=key.pubkey,
                         sha_hash=txdoc.sha_hash,
                         written_block=0,
                         blockstamp=blockstamp,
                         timestamp=time,
                         signatures=txdoc.signatures,
                         issuers=[key.pubkey],
                         receivers=[receiver],
                         amount=amount,
                         amount_base=amount_base,
                         comment=txdoc.comment,
                         txid=0,
                         state=Transaction.TO_SEND,
                         local=True,
                         raw=txdoc.signed_raw())
        forged_tx.append(tx)
        return forged_tx
Example #3
0
 async def initialize_transactions(self, connection, log_stream):
     """
     Request transactions from the network to initialize data for a given pubkey
     :param sakia.data.entities.Connection connection:
     :param function log_stream:
     """
     history_data = await self._bma_connector.get(
         connection.currency,
         bma.tx.history,
         req_args={'pubkey': connection.pubkey})
     txid = 0
     nb_tx = len(history_data["history"]["sent"]) + len(
         history_data["history"]["received"])
     log_stream("Found {0} transactions".format(nb_tx))
     transactions = []
     for sent_data in history_data["history"]["sent"] + history_data[
             "history"]["received"]:
         sent = TransactionDoc.from_bma_history(history_data["currency"],
                                                sent_data)
         log_stream("{0}/{1} transactions".format(txid, nb_tx))
         try:
             tx = parse_transaction_doc(sent, connection.pubkey,
                                        sent_data["block_number"],
                                        sent_data["time"], txid)
             transactions.append(tx)
             self._repo.insert(tx)
         except sqlite3.IntegrityError:
             log_stream("Transaction already registered in database")
         await asyncio.sleep(0)
         txid += 1
     return transactions
Example #4
0
 def restore_sources(self, pubkey, tx):
     """
     Restore the sources of a cancelled tx
     :param sakia.entities.Transaction tx:
     """
     txdoc = TransactionDoc.from_signed_raw(tx.raw)
     for offset, output in enumerate(txdoc.outputs):
         if output.conditions.left.pubkey == pubkey:
             source = Source(currency=self.currency,
                             pubkey=pubkey,
                             identifier=txdoc.sha_hash,
                             type='T',
                             noffset=offset,
                             amount=output.amount,
                             base=output.base)
             self._sources_processor.drop(source)
     for index, input in enumerate(txdoc.inputs):
         source = Source(currency=self.currency,
                         pubkey=txdoc.issuers[0],
                         identifier=input.origin_id,
                         type=input.source,
                         noffset=input.index,
                         amount=input.amount,
                         base=input.base)
         if source.pubkey == pubkey:
             self._sources_processor.insert(source)
Example #5
0
    def send_money(self, amount, sources, receiver, blockstamp, message):

        result = self.outputs_from_sources(amount, sources)
        inputs = result[0]
        computed_outputs = result[1]
        overheads = result[2]

        unlocks = []
        for i, s in enumerate(sources):
            unlocks.append(Unlock(i, [SIGParameter(0)]))
        outputs = self.tx_outputs(receiver, computed_outputs, overheads)

        tx = Transaction(3, self.currency, blockstamp, 0, [self.key.pubkey],
                         inputs, unlocks, outputs, message, None)
        tx.sign([self.key])
        return tx
Example #6
0
 async def parse_transactions_history(self, connections, start, end):
     """
     Request transactions from the network to initialize data for a given pubkey
     :param List[sakia.data.entities.Connection] connections: the list of connections found by tx parsing
     :param int start: the first block
     :param int end: the last block
     """
     transfers_changed = []
     new_transfers = {}
     for connection in connections:
         txid = 0
         new_transfers[connection] = []
         history_data = await self._bma_connector.get(self.currency, bma.tx.blocks,
                                                      req_args={'pubkey': connection.pubkey,
                                                                'start': start,
                                                                'end': end})
         for tx_data in history_data["history"]["sent"]:
             for tx in [t for t in self._transactions_processor.awaiting(self.currency)]:
                 if self._transactions_processor.run_state_transitions(tx, tx_data["hash"], tx_data["block_number"]):
                     transfers_changed.append(tx)
                     self._logger.debug("New transaction validated : {0}".format(tx.sha_hash))
         for tx_data in history_data["history"]["received"]:
             tx_doc = TransactionDoc.from_bma_history(history_data["currency"], tx_data)
             if not self._transactions_processor.find_by_hash(connection.pubkey, tx_doc.sha_hash) \
                 and SimpleTransaction.is_simple(tx_doc):
                 tx = parse_transaction_doc(tx_doc, connection.pubkey, tx_data["block_number"],
                                            tx_data["time"], txid)
                 if tx:
                     new_transfers[connection].append(tx)
                     self._transactions_processor.commit(tx)
                 else:
                     logging.debug("Error during transfer parsing")
     return transfers_changed, new_transfers
def get_transaction_document(current_block: dict, source: dict,
                             from_pubkey: str, to_pubkey: str) -> Transaction:
    """
    Return a Transaction document

    :param current_block: Current block infos
    :param source: Source to send
    :param from_pubkey: Public key of the issuer
    :param to_pubkey: Public key of the receiver

    :return: Transaction
    """
    # list of inputs (sources)
    inputs = [
        InputSource(
            amount=source["amount"],
            base=source["base"],
            source=source["type"],
            origin_id=source["identifier"],
            index=source["noffset"],
        )
    ]

    # list of issuers of the inputs
    issuers = [from_pubkey]

    # list of unlocks of the inputs
    unlocks = [
        Unlock(
            # inputs[index]
            index=0,
            # unlock inputs[index] if signatures[0] is from public key of issuers[0]
            parameters=[SIGParameter(0)],
        )
    ]

    # lists of outputs
    outputs = [
        OutputSource(
            amount=source["amount"],
            base=source["base"],
            condition="SIG({0})".format(to_pubkey),
        )
    ]

    transaction = Transaction(
        version=TRANSACTION_VERSION,
        currency=current_block["currency"],
        blockstamp=BlockUID(current_block["number"], current_block["hash"]),
        locktime=0,
        issuers=issuers,
        inputs=inputs,
        unlocks=unlocks,
        outputs=outputs,
        comment="",
        signatures=[],
    )

    return transaction
Example #8
0
    async def parse_dividends_history(self, connections, blocks, transactions):
        """
        Request transactions from the network to initialize data for a given pubkey
        :param List[sakia.data.entities.Connection] connections: the list of connections found by tx parsing
        :param List[duniterpy.documents.Block] blocks: the list of transactions found by tx parsing
        :param List[sakia.data.entities.Transaction] transactions: the list of transactions found by tx parsing
        """
        min_block_number = blocks[0].number
        max_block_number = blocks[-1].number
        dividends = {}
        for connection in connections:
            dividends[connection] = []
            history_data = await self._bma_connector.get(
                self.currency,
                bma.ud.history,
                req_args={'pubkey': connection.pubkey})
            block_numbers = []
            for ud_data in history_data["history"]["history"]:
                dividend = Dividend(currency=self.currency,
                                    pubkey=connection.pubkey,
                                    block_number=ud_data["block_number"],
                                    timestamp=ud_data["time"],
                                    amount=ud_data["amount"],
                                    base=ud_data["base"])
                if max_block_number >= dividend.block_number >= min_block_number:
                    self._logger.debug("Dividend of block {0}".format(
                        dividend.block_number))
                    block_numbers.append(dividend.block_number)
                    if self._dividends_processor.commit(dividend):
                        dividends[connection].append(dividend)

            for tx in transactions[connection]:
                txdoc = TransactionDoc.from_signed_raw(tx.raw)
                for input in txdoc.inputs:
                    # For each dividends inputs, if it is consumed (not present in ud history)
                    if input.source == "D" and input.origin_id == connection.pubkey and input.index not in block_numbers:
                        try:
                            # we try to get the block of the dividend
                            block = next(
                                (b for b in blocks if b.number == input.index))
                        except StopIteration:
                            block_data = await self._bma_connector.get(
                                self.currency,
                                bma.blockchain.block,
                                req_args={'number': input.index})
                            block = Block.from_signed_raw(
                                block_data["raw"] + block_data["signature"] +
                                "\n")
                        dividend = Dividend(currency=self.currency,
                                            pubkey=connection.pubkey,
                                            block_number=input.index,
                                            timestamp=block.mediantime,
                                            amount=block.ud,
                                            base=block.unit_base)
                        self._logger.debug("Dividend of block {0}".format(
                            dividend.block_number))
                        if self._dividends_processor.commit(dividend):
                            dividends[connection].append(dividend)
        return dividends
Example #9
0
 async def process(self, request):
     data = await request.post()
     if self.reject_next_post:
         self.reject_next_post = False
         return {'ucode': errors.UNHANDLED, 'message': "Rejected"}, 400
     transaction = Transaction.from_signed_raw(data["transaction"])
     self.forge.pool.append(transaction)
     return {}, 200
Example #10
0
    async def initialize_dividends(self, connection, transactions, log_stream,
                                   progress):
        """
        Request transactions from the network to initialize data for a given pubkey
        :param sakia.data.entities.Connection connection:
        :param List[sakia.data.entities.Transaction] transactions: the list of transactions found by tx processor
        :param function log_stream:
        :param function progress: progress callback
        """
        blockchain = self._blockchain_repo.get_one(
            currency=connection.currency)
        avg_blocks_per_month = int(30 * 24 * 3600 /
                                   blockchain.parameters.avg_gen_time)
        start = blockchain.current_buid.number - avg_blocks_per_month
        history_data = await self._bma_connector.get(
            connection.currency,
            bma.ud.history,
            req_args={'pubkey': connection.pubkey})
        block_numbers = []
        dividends = []
        for ud_data in history_data["history"]["history"]:
            if ud_data["block_number"] > start:
                dividend = Dividend(currency=connection.currency,
                                    pubkey=connection.pubkey,
                                    block_number=ud_data["block_number"],
                                    timestamp=ud_data["time"],
                                    amount=ud_data["amount"],
                                    base=ud_data["base"])
                log_stream("Dividend of block {0}".format(
                    dividend.block_number))
                block_numbers.append(dividend.block_number)
                try:
                    dividends.append(dividend)
                    self._repo.insert(dividend)
                except sqlite3.IntegrityError:
                    log_stream("Dividend already registered in database")

        for tx in transactions:
            txdoc = Transaction.from_signed_raw(tx.raw)
            for input in txdoc.inputs:
                if input.source == "D" and input.origin_id == connection.pubkey \
                        and input.index not in block_numbers and input.index > start:
                    diff_blocks = blockchain.current_buid.number - input.index
                    ud_mediantime = blockchain.median_time - diff_blocks * blockchain.parameters.avg_gen_time
                    dividend = Dividend(currency=connection.currency,
                                        pubkey=connection.pubkey,
                                        block_number=input.index,
                                        timestamp=ud_mediantime,
                                        amount=input.amount,
                                        base=input.base)
                    log_stream("Dividend of block {0}".format(
                        dividend.block_number))
                    try:
                        dividends.append(dividend)
                        self._repo.insert(dividend)
                    except sqlite3.IntegrityError:
                        log_stream("Dividend already registered in database")
        return dividends
Example #11
0
    async def initialize_dividends(self, connection, transactions, log_stream):
        """
        Request transactions from the network to initialize data for a given pubkey
        :param sakia.data.entities.Connection connection:
        :param List[sakia.data.entities.Transaction] transactions: the list of transactions found by tx processor
        :param function log_stream:
        """
        history_data = await self._bma_connector.get(
            connection.currency,
            bma.ud.history,
            req_args={'pubkey': connection.pubkey})
        log_stream("Found {0} available dividends".format(
            len(history_data["history"]["history"])))
        block_numbers = []
        dividends = []
        for ud_data in history_data["history"]["history"]:
            dividend = Dividend(currency=connection.currency,
                                pubkey=connection.pubkey,
                                block_number=ud_data["block_number"],
                                timestamp=ud_data["time"],
                                amount=ud_data["amount"],
                                base=ud_data["base"])
            log_stream("Dividend of block {0}".format(dividend.block_number))
            block_numbers.append(dividend.block_number)
            try:
                dividends.append(dividend)
                self._repo.insert(dividend)
            except sqlite3.IntegrityError:
                log_stream("Dividend already registered in database")

        for tx in transactions:
            txdoc = Transaction.from_signed_raw(tx.raw)
            for input in txdoc.inputs:
                if input.source == "D" and input.origin_id == connection.pubkey and input.index not in block_numbers:
                    block = await self._bma_connector.get(
                        connection.currency,
                        bma.blockchain.block,
                        req_args={'number': input.index})
                    await asyncio.sleep(0.5)

                    dividend = Dividend(currency=connection.currency,
                                        pubkey=connection.pubkey,
                                        block_number=input.index,
                                        timestamp=block["medianTime"],
                                        amount=block["dividend"],
                                        base=block["unitbase"])
                    log_stream("Dividend of block {0}".format(
                        dividend.block_number))
                    try:
                        dividends.append(dividend)
                        self._repo.insert(dividend)
                    except sqlite3.IntegrityError:
                        log_stream("Dividend already registered in database")
        return dividends
Example #12
0
def get_transaction_document(current_block, source, from_pubkey, to_pubkey):
    """
    Return a Transaction document

    :param dict current_block: Current block infos
    :param dict source: Source to send
    :param str from_pubkey: Public key of the issuer
    :param str to_pubkey: Public key of the receiver

    :return: Transaction
    """
    # list of inputs (sources)
    inputs = [
        InputSource(amount=source['amount'],
                    base=source['base'],
                    source=source['type'],
                    origin_id=source['identifier'],
                    index=source['noffset'])
    ]

    # list of issuers of the inputs
    issuers = [from_pubkey]

    # list of unlocks of the inputs
    unlocks = [
        Unlock(
            # inputs[index]
            index=0,
            # unlock inputs[index] if signatures[0] is from public key of issuers[0]
            parameters=[SIGParameter(0)])
    ]

    # lists of outputs
    outputs = [
        OutputSource(
            amount=source['amount'],
            base=source['base'],
            # only the receiver of the output can use it as input in another transaction
            conditions=Condition.token(SIG.token(to_pubkey)))
    ]

    transaction = Transaction(version=TRANSACTION_VERSION,
                              currency=current_block['currency'],
                              blockstamp=BlockUID(current_block['number'],
                                                  current_block['hash']),
                              locktime=0,
                              issuers=issuers,
                              inputs=inputs,
                              unlocks=unlocks,
                              outputs=outputs,
                              comment='',
                              signatures=None)

    return transaction
Example #13
0
File: tx.py Project: duniter/silkaj
async def generate_transaction_document(
    issuers,
    tx_amounts,
    listinput_and_amount,
    outputAddresses,
    Comment="",
    OutputbackChange=None,
):

    listinput = listinput_and_amount[0]
    totalAmountInput = listinput_and_amount[1]
    total_tx_amount = sum(tx_amounts)

    head_block = await HeadBlock().head_block
    currency_name = head_block["currency"]
    blockstamp_current = BlockUID(head_block["number"], head_block["hash"])
    curentUnitBase = head_block["unitbase"]

    if not OutputbackChange:
        OutputbackChange = issuers

    # if it's not a foreign exchange transaction, we remove units after 2 digits after the decimal point.
    if issuers not in outputAddresses:
        total_tx_amount = (total_tx_amount //
                           10**curentUnitBase) * 10**curentUnitBase

    # Generate output
    ################
    listoutput = []
    for tx_amount, outputAddress in zip(tx_amounts, outputAddresses):
        generate_output(listoutput, curentUnitBase, tx_amount, outputAddress)

    # Outputs to himself
    rest = totalAmountInput - total_tx_amount
    generate_output(listoutput, curentUnitBase, rest, OutputbackChange)

    # Unlocks
    unlocks = generate_unlocks(listinput)

    # Generate transaction document
    ##############################

    return Transaction(
        version=10,
        currency=currency_name,
        blockstamp=blockstamp_current,
        locktime=0,
        issuers=[issuers],
        inputs=listinput,
        unlocks=unlocks,
        outputs=listoutput,
        comment=Comment,
        signatures=[],
    )
Example #14
0
    async def initialize_dividends(self, connection, transactions, log_stream, progress):
        """
        Request transactions from the network to initialize data for a given pubkey
        :param sakia.data.entities.Connection connection:
        :param List[sakia.data.entities.Transaction] transactions: the list of transactions found by tx processor
        :param function log_stream:
        :param function progress: progress callback
        """
        blockchain = self._blockchain_repo.get_one(currency=connection.currency)
        avg_blocks_per_month = int(30 * 24 * 3600 / blockchain.parameters.avg_gen_time)
        start = blockchain.current_buid.number - avg_blocks_per_month
        history_data = await self._bma_connector.get(connection.currency, bma.ud.history,
                                                     req_args={'pubkey': connection.pubkey})
        block_numbers = []
        dividends = []
        for ud_data in history_data["history"]["history"]:
            if ud_data["block_number"] > start:
                dividend = Dividend(currency=connection.currency,
                                    pubkey=connection.pubkey,
                                    block_number=ud_data["block_number"],
                                    timestamp=ud_data["time"],
                                    amount=ud_data["amount"],
                                    base=ud_data["base"])
                log_stream("Dividend of block {0}".format(dividend.block_number))
                block_numbers.append(dividend.block_number)
                try:
                    dividends.append(dividend)
                    self._repo.insert(dividend)
                except sqlite3.IntegrityError:
                    log_stream("Dividend already registered in database")

        for tx in transactions:
            txdoc = Transaction.from_signed_raw(tx.raw)
            for input in txdoc.inputs:
                if input.source == "D" and input.origin_id == connection.pubkey \
                        and input.index not in block_numbers and input.index > start:
                    diff_blocks = blockchain.current_buid.number - input.index
                    ud_mediantime = blockchain.median_time - diff_blocks*blockchain.parameters.avg_gen_time
                    dividend = Dividend(currency=connection.currency,
                                        pubkey=connection.pubkey,
                                        block_number=input.index,
                                        timestamp=ud_mediantime,
                                        amount=input.amount,
                                        base=input.base)
                    log_stream("Dividend of block {0}".format(dividend.block_number))
                    try:
                        dividends.append(dividend)
                        self._repo.insert(dividend)
                    except sqlite3.IntegrityError:
                        log_stream("Dividend already registered in database")
        return dividends
Example #15
0
 def parse_transaction_inputs(self, pubkey, transaction):
     """
     Parse a transaction
     :param sakia.data.entities.Transaction transaction:
     """
     txdoc = TransactionDoc.from_signed_raw(transaction.raw)
     for index, input in enumerate(txdoc.inputs):
         source = Source(currency=self.currency,
                         pubkey=txdoc.issuers[0],
                         identifier=input.origin_id,
                         type=input.source,
                         noffset=input.index,
                         amount=input.amount,
                         base=input.base)
         if source.pubkey == pubkey:
             self._sources_processor.drop(source)
Example #16
0
 def parse_transaction_outputs(self, pubkey, transaction):
     """
     Parse a transaction
     :param sakia.data.entities.Transaction transaction:
     """
     txdoc = TransactionDoc.from_signed_raw(transaction.raw)
     for offset, output in enumerate(txdoc.outputs):
         if output.conditions.left.pubkey == pubkey:
             source = Source(currency=self.currency,
                             pubkey=pubkey,
                             identifier=txdoc.sha_hash,
                             type='T',
                             noffset=offset,
                             amount=output.amount,
                             base=output.base)
             self._sources_processor.insert(source)
Example #17
0
 async def initialize_transactions(self, connection, log_stream, progress):
     """
     Request transactions from the network to initialize data for a given pubkey
     :param sakia.data.entities.Connection connection:
     :param function log_stream:
     :param function progress: progress callback
     """
     blockchain = self._blockchain_repo.get_one(
         currency=connection.currency)
     avg_blocks_per_month = int(30 * 24 * 3600 /
                                blockchain.parameters.avg_gen_time)
     start = blockchain.current_buid.number - avg_blocks_per_month
     end = blockchain.current_buid.number
     history_data = await self._bma_connector.get(connection.currency,
                                                  bma.tx.blocks,
                                                  req_args={
                                                      'pubkey':
                                                      connection.pubkey,
                                                      'start': start,
                                                      'end': end
                                                  })
     txid = 0
     nb_tx = len(history_data["history"]["sent"]) + len(
         history_data["history"]["received"])
     log_stream("Found {0} transactions".format(nb_tx))
     transactions = []
     for sent_data in history_data["history"]["sent"] + history_data[
             "history"]["received"]:
         sent = TransactionDoc.from_bma_history(history_data["currency"],
                                                sent_data)
         log_stream("{0}/{1} transactions".format(txid, nb_tx))
         progress(1 / nb_tx)
         try:
             tx = parse_transaction_doc(sent, connection.pubkey,
                                        sent_data["block_number"],
                                        sent_data["time"], txid)
             if tx:
                 transactions.append(tx)
                 self._repo.insert(tx)
             else:
                 log_stream("ERROR : Could not parse transaction")
         except sqlite3.IntegrityError:
             log_stream("Transaction already registered in database")
         await asyncio.sleep(0)
         txid += 1
     return transactions
Example #18
0
 async def parse_transactions_history(self, connections, start, end):
     """
     Request transactions from the network to initialize data for a given pubkey
     :param List[sakia.data.entities.Connection] connections: the list of connections found by tx parsing
     :param int start: the first block
     :param int end: the last block
     """
     transfers_changed = []
     new_transfers = {}
     for connection in connections:
         txid = 0
         new_transfers[connection] = []
         history_data = await self._bma_connector.get(self.currency,
                                                      bma.tx.blocks,
                                                      req_args={
                                                          'pubkey':
                                                          connection.pubkey,
                                                          'start': start,
                                                          'end': end
                                                      })
         for tx_data in history_data["history"]["sent"]:
             for tx in [
                     t for t in self._transactions_processor.awaiting(
                         self.currency)
             ]:
                 if self._transactions_processor.run_state_transitions(
                         tx, tx_data["hash"], tx_data["block_number"]):
                     transfers_changed.append(tx)
                     self._logger.debug(
                         "New transaction validated : {0}".format(
                             tx.sha_hash))
         for tx_data in history_data["history"]["received"]:
             tx_doc = TransactionDoc.from_bma_history(
                 history_data["currency"], tx_data)
             if not self._transactions_processor.find_by_hash(connection.pubkey, tx_doc.sha_hash) \
                 and SimpleTransaction.is_simple(tx_doc):
                 tx = parse_transaction_doc(tx_doc, connection.pubkey,
                                            tx_data["block_number"],
                                            tx_data["time"], txid)
                 if tx:
                     new_transfers[connection].append(tx)
                     self._transactions_processor.commit(tx)
                 else:
                     logging.debug("Error during transfer parsing")
     return transfers_changed, new_transfers
Example #19
0
    async def parse_dividends_history(self, connections, start, end, transactions):
        """
        Request transactions from the network to initialize data for a given pubkey
        :param List[sakia.data.entities.Connection] connections: the list of connections found by tx parsing
        :param List[duniterpy.documents.Block] blocks: the list of transactions found by tx parsing
        :param List[sakia.data.entities.Transaction] transactions: the list of transactions found by tx parsing
        """
        dividends = {}
        for connection in connections:
            dividends[connection] = []
            history_data = await self._bma_connector.get(self.currency, bma.ud.history,
                                                         req_args={'pubkey': connection.pubkey})
            block_numbers = []
            for ud_data in history_data["history"]["history"]:
                dividend = Dividend(currency=self.currency,
                                    pubkey=connection.pubkey,
                                    block_number=ud_data["block_number"],
                                    timestamp=ud_data["time"],
                                    amount=ud_data["amount"],
                                    base=ud_data["base"])
                if start <= dividend.block_number <= end:
                    self._logger.debug("Dividend of block {0}".format(dividend.block_number))
                    block_numbers.append(dividend.block_number)
                    if self._dividends_processor.commit(dividend):
                        dividends[connection].append(dividend)

            for tx in transactions[connection]:
                txdoc = TransactionDoc.from_signed_raw(tx.raw)
                for input in txdoc.inputs:
                    # For each dividends inputs, if it is consumed (not present in ud history)
                    if input.source == "D" and input.origin_id == connection.pubkey and input.index not in block_numbers:
                        block_data = await self._bma_connector.get(self.currency, bma.blockchain.block,
                                                              req_args={'number': input.index})
                        block = Block.from_signed_raw(block_data["raw"] + block_data["signature"] + "\n")
                        dividend = Dividend(currency=self.currency,
                                            pubkey=connection.pubkey,
                                            block_number=input.index,
                                            timestamp=block.mediantime,
                                            amount=block.ud,
                                            base=block.unit_base)
                        self._logger.debug("Dividend of block {0}".format(dividend.block_number))
                        if self._dividends_processor.commit(dividend):
                            dividends[connection].append(dividend)
        return dividends
Example #20
0
 async def initialize_transactions(self, connection, log_stream, progress):
     """
     Request transactions from the network to initialize data for a given pubkey
     :param sakia.data.entities.Connection connection:
     :param function log_stream:
     :param function progress: progress callback
     """
     blockchain = self._blockchain_repo.get_one(currency=connection.currency)
     avg_blocks_per_month = int(30 * 24 * 3600 / blockchain.parameters.avg_gen_time)
     start = blockchain.current_buid.number - avg_blocks_per_month
     end = blockchain.current_buid.number
     history_data = await self._bma_connector.get(connection.currency, bma.tx.blocks,
                                                  req_args={'pubkey': connection.pubkey,
                                                            'start': start,
                                                            'end': end})
     txid = 0
     nb_tx = len(history_data["history"]["sent"]) + len(history_data["history"]["received"])
     log_stream("Found {0} transactions".format(nb_tx))
     transactions = []
     for sent_data in history_data["history"]["sent"] + history_data["history"]["received"]:
         sent = TransactionDoc.from_bma_history(history_data["currency"], sent_data)
         log_stream("{0}/{1} transactions".format(txid, nb_tx))
         progress(1 / nb_tx)
         try:
             tx = parse_transaction_doc(sent, connection.pubkey, sent_data["block_number"],
                                        sent_data["time"], txid)
             if tx:
                 transactions.append(tx)
                 self._repo.insert(tx)
             else:
                 log_stream("ERROR : Could not parse transaction")
         except sqlite3.IntegrityError:
             log_stream("Transaction already registered in database")
         await asyncio.sleep(0)
         txid += 1
     return transactions
Example #21
0
 def txdoc(self):
     """
     :rtype: duniterpy.documents.Transaction
     """
     return TransactionDoc.from_signed_raw(self.raw)
Example #22
0
 def txdoc(self):
     """
     :rtype: duniterpy.documents.Transaction
     """
     return TransactionDoc.from_signed_raw(self.raw)