Example #1
0
    def get_spent(self, txid, output, current_transactions=[]):
        transactions = backend.query.get_spent(self.connection, txid, output)
        transactions = list(transactions) if transactions else []
        if len(transactions) > 1:
            raise core_exceptions.CriticalDoubleSpend(
                '`{}` was spent more than once. There is a problem'
                ' with the chain'.format(txid))

        current_spent_transactions = []
        for ctxn in current_transactions:
            for ctxn_input in ctxn.inputs:
                if ctxn_input.fulfills and\
                   ctxn_input.fulfills.txid == txid and\
                   ctxn_input.fulfills.output == output:
                    current_spent_transactions.append(ctxn)

        transaction = None
        if len(transactions) + len(current_spent_transactions) > 1:
            raise DoubleSpend('tx "{}" spends inputs twice'.format(txid))
        elif transactions:
            transaction = Transaction.from_db(self, transactions[0])
        elif current_spent_transactions:
            transaction = current_spent_transactions[0]

        return transaction
Example #2
0
    def get_spent(self, txid, output, current_transactions=[]):
        transactions = backend.query.get_spent(self.connection, txid, output)
        transactions = list(transactions) if transactions else []

        for ctxn in current_transactions:
            for ctxn_input in ctxn.inputs:
                if ctxn_input.fulfills.txid == txid and\
                   ctxn_input.fulfills.output == output:
                    transactions.append(ctxn.to_dict())

        transaction = None
        if len(transactions) > 1:
            raise core_exceptions.CriticalDoubleSpend(
                '`{}` was spent more than once. There is a problem'
                ' with the chain'.format(txid))
        elif transactions:
            transaction = transactions[0]

        if transaction and transaction['operation'] == 'CREATE':
            asset = backend.query.get_asset(self.connection, transaction['id'])

            if asset:
                transaction['asset'] = asset
            else:
                transaction['asset'] = {'data': None}

            return Transaction.from_dict(transaction)
        elif transaction and transaction['operation'] == 'TRANSFER':
            return Transaction.from_dict(transaction)
        else:
            return None
Example #3
0
    def get_spent(self, txid, output):
        """Check if a `txid` was already used as an input.

        A transaction can be used as an input for another transaction. Bigchain
        needs to make sure that a given `(txid, output)` is only used once.

        This method will check if the `(txid, output)` has already been
        spent in a transaction that is in either the `VALID`, `UNDECIDED` or
        `BACKLOG` state.

        Args:
            txid (str): The id of the transaction
            output (num): the index of the output in the respective transaction

        Returns:
            The transaction (Transaction) that used the `(txid, output)` as an
            input else `None`

        Raises:
            CriticalDoubleSpend: If the given `(txid, output)` was spent in
            more than one valid transaction.
        """
        # checks if an input was already spent
        # checks if the bigchain has any transaction with input {'txid': ...,
        # 'output': ...}
        transactions = list(
            backend.query.get_spent(self.connection, txid, output))

        # a transaction_id should have been spent at most one time
        # determine if these valid transactions appear in more than one valid
        # block
        num_valid_transactions = 0
        non_invalid_transactions = []
        for transaction in transactions:
            # ignore transactions in invalid blocks
            # FIXME: Isn't there a faster solution than doing I/O again?
            txn, status = self.get_transaction(transaction['id'],
                                               include_status=True)
            if status == self.TX_VALID:
                num_valid_transactions += 1
            # `txid` can only have been spent in at most on valid block.
            if num_valid_transactions > 1:
                raise core_exceptions.CriticalDoubleSpend(
                    '`{}` was spent more than once. There is a problem'
                    ' with the chain'.format(txid))
            # if its not and invalid transaction
            if status is not None:
                transaction.update({'metadata': txn.metadata})
                non_invalid_transactions.append(transaction)

        if non_invalid_transactions:
            return Transaction.from_dict(non_invalid_transactions[0])
Example #4
0
    def get_spent(self, txid, output):
        """Check if a `txid` was already used as an input.

        A transaction can be used as an input for another transaction. Bigchain needs to make sure that a
        given `txid` is only used once.

        Args:
            txid (str): The id of the transaction
            output (num): the index of the output in the respective transaction

        Returns:
            The transaction (Transaction) that used the `txid` as an input else
            `None`
        """
        # checks if an input was already spent
        # checks if the bigchain has any transaction with input {'txid': ...,
        # 'output': ...}
        transactions = list(
            backend.query.get_spent(self.connection, txid, output))

        # a transaction_id should have been spent at most one time
        if transactions:
            # determine if these valid transactions appear in more than one valid block
            num_valid_transactions = 0
            for transaction in transactions:
                # ignore invalid blocks
                # FIXME: Isn't there a faster solution than doing I/O again?
                if self.get_transaction(transaction['id']):
                    num_valid_transactions += 1
                if num_valid_transactions > 1:
                    raise core_exceptions.CriticalDoubleSpend(
                        '`{}` was spent more than once. There is a problem'
                        ' with the chain'.format(txid))

            if num_valid_transactions:
                return Transaction.from_dict(transactions[0])
            else:
                # all queried transactions were invalid
                return None
        else:
            return None