예제 #1
0
    def prepare_incomplete_inputs(
            self,
            inputs: List[WalletInputInfo],
            tx_storage: TransactionStorage,
            force: bool = False) -> List[WalletInputInfo]:
        """Adds the keys to the inputs

        :param inputs: list of inputs of the tx
        :type inputs: List[WalletInputInfo]

        :param force: if True we will search the private key not only in the unspent txs
            this parameter, when set to True, can be used to allow a double spending
        :type force: bool

        :param tx_storage: storage to search for output tx
        :type tx_storage: TransactionStorage

        :raises PrivateKeyNotFound: when trying to spend output and we don't have the corresponding
            key in our wallet
        """
        if len(inputs) != len(set(inputs)):
            # Same input is used more than once
            raise InputDuplicated
        new_inputs: List[WalletInputInfo] = []
        for _input in inputs:
            new_input = None
            output_tx = tx_storage.get_transaction(_input.tx_id)
            output = output_tx.outputs[_input.index]
            token_id = output_tx.get_token_uid(output.get_token_index())
            key = (_input.tx_id, _input.index)
            # we'll remove this utxo so it can't be selected again shortly
            utxo = self.unspent_txs[token_id].pop(key, None)
            if utxo is None:
                utxo = self.maybe_spent_txs[token_id].pop(key, None)
            if utxo:
                new_input = WalletInputInfo(_input.tx_id, _input.index,
                                            self.get_private_key(utxo.address))
                utxo.maybe_spent_ts = int(self.reactor.seconds())
                self.maybe_spent_txs[token_id][key] = utxo
            elif force:
                script_type = parse_address_script(output.script)

                if script_type:
                    address = script_type.address
                    if address in self.keys:
                        new_input = WalletInputInfo(
                            _input.tx_id, _input.index,
                            self.get_private_key(address))

            if new_input:
                new_inputs.insert(0, new_input)
            else:
                raise PrivateKeyNotFound

        return new_inputs
예제 #2
0
def validate_tx_hash(hash_hex: str,
                     tx_storage: TransactionStorage) -> Tuple[bool, str]:
    """ Validate if the tx hash is valid and if it exists
        Return success and a message in case of failure
    """
    success = True
    message = ''
    pattern = r'[a-fA-F\d]{64}'
    # Check if parameter is a valid hex hash
    if not re.match(pattern, hash_hex):
        success = False
        message = 'Invalid hash'
    else:
        try:
            tx_storage.get_transaction(bytes.fromhex(hash_hex))
        except TransactionDoesNotExist:
            success = False
            message = 'Transaction not found'

    return success, message
예제 #3
0
    def match_inputs(
        self, inputs: List[TxInput], tx_storage: TransactionStorage
    ) -> Iterable[Tuple[TxInput, Optional[str]]]:
        """Returns an iterable with the inputs that belong and don't belong to this wallet

        :return: An iterable with the inputs and corresponding address, if it belongs to this wallet
        :rtype: Iterable[(TxInput, str(base58))]
        """
        for _input in inputs:
            output_tx = tx_storage.get_transaction(_input.tx_id)
            output = output_tx.outputs[_input.index]
            token_id = output_tx.get_token_uid(output.get_token_index())
            utxo = self.unspent_txs[token_id].get((_input.tx_id, _input.index))
            if utxo is None:
                utxo = self.maybe_spent_txs[token_id].get(
                    (_input.tx_id, _input.index))
            # is it in our wallet?
            if utxo:
                yield _input, utxo.address
            else:
                # we couldn't find the UTXO, so it's not ours
                yield _input, None