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
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
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