Ejemplo n.º 1
0
    def _calculate_hash(self, filename, **kwargs):
        """
        Calculates the hash of the file and the hash of the file + metadata
        (passed in ``kwargs``).

        Args:
            filename (str): Name of the file
            testnet (bool): testnet flag. Defaults to False
            **kwargs: Additional metadata to be encoded with the file. Only
                the values are used to compute the hash. Values are
                ordered using their keys, so that the computation of the
                hash is consistent. As an example, given::

                    File('filename', title='piece title', artist='artist')

                the values ``('artist', 'piece title')`` would be used in that
                order for the computation of the hash.

        """
        with open(filename, 'rb') as f:
            file_hash = hashlib.md5(f.read()).hexdigest()

        if kwargs:
            data = str(
                [urepr(kwargs[k]) for k in sorted(kwargs)] + [file_hash])
        else:
            data = file_hash

        address_piece_with_metadata = str(
            bin_to_b58check(bin_hash160(data.encode()),
                            magicbyte=self._magicbyte)
        )
        address_piece = str(bin_to_b58check(bin_hash160(file_hash.encode()),
                                            magicbyte=self._magicbyte))
        return address_piece, address_piece_with_metadata
Ejemplo n.º 2
0
def pkvkey2adrw(pvkey, network=5):
    pub_hex = bitcoin.privtopub(pvkey)
    pub_bin = bitcoin.encode_pubkey(pub_hex, "bin_compressed")
    PKH = bitcoin.bin_hash160(pub_bin)
    script = "\0\x14" + PKH
    address_bin = bitcoin.bin_hash160(script)
    address = bitcoin.bin_to_b58check(address_bin, network)
    assert bitcoin.p2sh_scriptaddr(script, network) == address
    return address
Ejemplo n.º 3
0
    def pubkey_to_address(self, pubkey, magicbyte=0, magicbyte_length=1):
        """
        根据pubkey生成地址
        """
        if isinstance(pubkey, (list, tuple)):
            pubkey = bitcoin.encode_pubkey(pubkey, 'bin')

        if len(pubkey) in [66, 130]:
            return self.bin_to_b58check(bitcoin.bin_hash160(bitcoin.binascii.unhexlify(pubkey)), magicbyte=magicbyte, magicbyte_length=magicbyte_length)

        return self.bin_to_b58check(bitcoin.bin_hash160(pubkey), magicbyte=magicbyte, magicbyte_length=magicbyte_length)
Ejemplo n.º 4
0
def pubkey_to_address(pubkey, isTestnet=False):
    base58_pubkey = TESTNET_MAGIC_BYTE if isTestnet else MAGIC_BYTE
    pubkey_bin = bytes.fromhex(pubkey)
    pub_hash = bitcoin.bin_hash160(pubkey_bin)
    data = bytes([base58_pubkey]) + pub_hash
    checksum = bitcoin.bin_dbl_sha256(data)[0:4]
    return b58encode(data + checksum)
Ejemplo n.º 5
0
    def append_inputs_to_TX(self, utxo, bip32_path):
        self.amount += int(utxo['value'])
        raw_tx = bytearray.fromhex(utxo['raw_tx'])
        
        # parse the raw transaction, so that we can extract the UTXO locking script we refer to
        prev_transaction = bitcoinTransaction(raw_tx)

        utxo_tx_index = utxo['tx_ouput_n']
        if utxo_tx_index < 0 or utxo_tx_index > len(prev_transaction.outputs):
            raise Exception('Incorrect value of outputIndex for UTXO %s-%d' % 
                            (utxo['raw_tx'], utxo['tx_ouput_n']))
        
        trusted_input = self.chip.getTrustedInput(prev_transaction, utxo_tx_index)
        self.trusted_inputs.append(trusted_input)
        
        # Hash check
        curr_pubkey = compress_public_key(self.chip.getWalletPublicKey(bip32_path)['publicKey'])
        pubkey_hash = bin_hash160(curr_pubkey)
        pubkey_hash_from_script = extract_pkh_from_locking_script(prev_transaction.outputs[utxo_tx_index].script)
        if pubkey_hash != pubkey_hash_from_script:
            text = "Error: The hashes for the public key for the BIP32 path, and the UTXO locking script do not match."
            text += "Your signed transaction will not be validated by the network.\n"
            text += "pubkey_hash: %s\n" % pubkey_hash.hex()
            text += "pubkey_hash_from_script: %s\n" % pubkey_hash_from_script.hex()
            printDbg(text)

        self.arg_inputs.append({
            'locking_script': prev_transaction.outputs[utxo['tx_ouput_n']].script,
            'pubkey': curr_pubkey,
            'bip32_path': bip32_path,
            'outputIndex': utxo['tx_ouput_n'],
            'txid': utxo['tx_hash']
        })
Ejemplo n.º 6
0
def pubkey_to_address(pub_key, dash_network: str):
    """Convert public key to a Dash address."""
    pubkey_bin = bytes.fromhex(pub_key)
    pub_hash = bitcoin.bin_hash160(pubkey_bin)
    data = bytes([get_chain_params(dash_network).PREFIX_PUBKEY_ADDRESS]) + pub_hash
    checksum = bitcoin.bin_dbl_sha256(data)[0:4]
    return base58.b58encode(data + checksum)
Ejemplo n.º 7
0
def pubkey2adr(pub_hex, network=5):
    pub_bin = bitcoin.encode_pubkey(pub_hex, "bin_compressed")
    PKH = bitcoin.bin_hash160(pub_bin)
    # script = "\0" + PKH
    # address_bin = bitcoin.bin_hash160(script)
    address = bitcoin.bin_to_b58check(PKH, 0)
    #assert bitcoin.p2sh_scriptaddr(script,network) == address
    return address
Ejemplo n.º 8
0
def pubkey_to_address(pubkey):
    """
    Based on project: https://github.com/chaeplin/dashmnb with some changes related to usage of bitcoin library.
    """
    pubkey_bin = bytes.fromhex(pubkey)
    pub_hash = bitcoin.bin_hash160(pubkey_bin)
    data = bytes([76]) + pub_hash
    checksum = bitcoin.bin_dbl_sha256(data)[0:4]
    return base58.b58encode(data + checksum)
Ejemplo n.º 9
0
    def _calculate_hash(self, filename, **kwargs):
        """
        Calculates the hash of the file and the hash of the file + metadata (passed on the keywargs)
        """

        # hash to address
        with open(filename, 'rb') as f:
            file_hash = hashlib.md5(f.read()).hexdigest()

        if kwargs:
            data = str([unicode(value) for value in kwargs.itervalues()] + [file_hash])
        else:
            data = file_hash
        address_piece_with_metadata = unicode(bitcoin.bin_to_b58check(bitcoin.bin_hash160(data),
                                                                             magicbyte=self._magicbyte))
        address_piece = unicode(bitcoin.bin_to_b58check(bitcoin.bin_hash160(file_hash),
                                                               magicbyte=self._magicbyte))
        return address_piece, address_piece_with_metadata
def gen_address_for_data(data):
    print("Hashing data: " + str(data))

    # https://gist.github.com/patricklodder/b27fb3e91c0566272976#file-gistfile1-py-L390
    # RIPEMD160(SHA256(data))
    fingerprint = bin_hash160(data.encode())
    print("Data fingerprint: " + str(fingerprint.encode('hex')))

    address = str(bin_to_b58check(fingerprint), magicbyte=_magicbyte)
    print("Final address: " + str(address))

    return address
def gen_address_for_data(data):
	print("Hashing data: "+str(data))

	# https://gist.github.com/patricklodder/b27fb3e91c0566272976#file-gistfile1-py-L390
	# RIPEMD160(SHA256(data))
	fingerprint = bin_hash160(data.encode())
	print("Data fingerprint: "+str(fingerprint.encode('hex')))

	address = str(bin_to_b58check(fingerprint), magicbyte=_magicbyte)
	print("Final address: "+str(address))

	return address
Ejemplo n.º 12
0
def extract_pkh_from_locking_script(script):
    if len(script) == 25:
        if script[0:1] == OP_DUP and script[1:2] == OP_HASH160:
            if read_varint(script, 2)[0] == 20:
                return script[3:23]
            else:
                raise Exception('Non-standard public key hash length (should be 20)')

        elif len(script) == 35:
            scriptlen = read_varint(script, 0)[0]
            if scriptlen in [32, 33]:
                return bin_hash160(script[1:1 + scriptlen])
            else:
                raise Exception('Non-standard public key length (should be 32 or 33)')
    raise Exception('Non-standard locking script type (should be P2PKH or P2PK). len is %d' % len(script))
Ejemplo n.º 13
0
def generate_mcaf(currencies, seed, mode="P"):
    priv = sha256(seed)
    pub = privtopub(priv)
    #import ipdb; ipdb.set_trace()
    hash160 = binascii.hexlify(bin_hash160(binascii.unhexlify(pub)))

    print(hash160, b58encode(hash160))

    if mode == 'P':
        address = "P%s0%s" % (encode_currency_support_token(currencies).decode(
            "utf-8"), b58encode(hash160).decode("utf-8"))
    else:
        raise NotImplementedError("Only P mode implemented")

    return "%s%s" % (address, sha256(address)[:4])
Ejemplo n.º 14
0
def generate_mcaf(currencies, seed, mode="P"):
    priv = sha256(seed)
    pub = privtopub(priv)
    #import ipdb; ipdb.set_trace()
    hash160 = binascii.hexlify(bin_hash160(binascii.unhexlify(pub)))

    print(hash160, b58encode(hash160))

    if mode == 'P':
        address = "P%s0%s" % (
            encode_currency_support_token(currencies).decode("utf-8"),
            b58encode(hash160).decode("utf-8")
        )
    else:
        raise NotImplementedError("Only P mode implemented")

    return "%s%s" % (address, sha256(address)[:4])
Ejemplo n.º 15
0
    def get_owner_key_to_display(self) -> str:
        ret = ''
        if self.masternode:
            if self.edit_mode:
                if self.masternode.dmn_owner_key_type == InputKeyType.PRIVATE:
                    ret = self.masternode.dmn_owner_private_key
                else:
                    ret = self.masternode.dmn_owner_address
            else:
                try:
                    if self.masternode.dmn_owner_key_type == InputKeyType.PRIVATE:
                        if self.act_view_as_owner_private_key.isChecked():
                            ret = self.masternode.dmn_owner_private_key
                        elif self.act_view_as_owner_public_address.isChecked():
                            if self.masternode.dmn_owner_private_key:
                                ret = crown_utils.wif_privkey_to_address(self.masternode.dmn_owner_private_key,
                                                                        self.app_config.crown_network)
                        elif self.act_view_as_owner_public_key.isChecked():
                            if self.masternode.dmn_owner_private_key:
                                ret = crown_utils.wif_privkey_to_pubkey(self.masternode.dmn_owner_private_key)
                        elif self.act_view_as_owner_public_key_hash.isChecked():
                            if self.masternode.dmn_owner_private_key:
                                pubkey = crown_utils.wif_privkey_to_pubkey(self.masternode.dmn_owner_private_key)
                                pubkey_bin = bytes.fromhex(pubkey)
                                pub_hash = bitcoin.bin_hash160(pubkey_bin)
                                ret = pub_hash.hex()
                        else:
                            ret = '???'
                    else:
                        if self.act_view_as_owner_public_address.isChecked():
                            ret = self.masternode.dmn_owner_address
                        elif self.act_view_as_owner_public_key_hash.isChecked():
                            ret = self.masternode.get_dmn_owner_pubkey_hash()
                        else:
                            ret = '???'
                except Exception as e:
                    msg = str(e)
                    if not msg:
                        msg = 'Key conversion error.'
                    WndUtils.errorMsg(msg)

        return ret
Ejemplo n.º 16
0
def get_xpub(client, bip32_path):
    bip32_path = clean_bip32_path(bip32_path)
    bip32_path.strip()
    if bip32_path.lower().find('m/') >= 0:
        bip32_path = bip32_path[2:]
    path_n = bip32_path_string_to_n(bip32_path)
    parent_bip32_path = bip32_path_n_to_string(path_n[:-1])
    depth = len(path_n)
    index = path_n[-1]

    nodedata = client.getWalletPublicKey(bip32_path)
    pubkey = compress(nodedata.get('publicKey'))
    chaincode = nodedata.get('chainCode')

    parent_nodedata = client.getWalletPublicKey(parent_bip32_path)
    parent_pubkey = compress(parent_nodedata['publicKey'])
    parent_fingerprint = bin_hash160(parent_pubkey)[:4]

    xpub_raw = bytes.fromhex('0488b21e') + depth.to_bytes(1, 'big') + parent_fingerprint + index.to_bytes(4, 'big') + \
           chaincode + pubkey
    xpub = Base58.check_encode(xpub_raw)

    return xpub
Ejemplo n.º 17
0
def pubkey_to_address(pubkey, isTestnet=False):
    pubkey_bin = bytes.fromhex(pubkey)
    pkey_hash = bitcoin.bin_hash160(pubkey_bin)
    return pubkeyhash_to_address(pkey_hash, isTestnet)
Ejemplo n.º 18
0
    def prepare_transfer_tx(self, caller, bip32_path, utxos_to_spend,
                            dest_address, tx_fee, rawtransactions):
        # For each UTXO create a Ledger 'trusted input'
        self.trusted_inputs = []
        #    https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand)
        self.arg_inputs = []
        self.amount = 0
        for idx, utxo in enumerate(utxos_to_spend):

            self.amount += int(utxo['value'])
            raw_tx = bytearray.fromhex(rawtransactions[utxo['tx_hash']])

            if not raw_tx:
                raise Exception("Can't find raw transaction for txid: " +
                                rawtransactions[utxo['tx_hash']])

            # parse the raw transaction, so that we can extract the UTXO locking script we refer to
            prev_transaction = bitcoinTransaction(raw_tx)

            utxo_tx_index = utxo['tx_ouput_n']
            if utxo_tx_index < 0 or utxo_tx_index > len(
                    prev_transaction.outputs):
                raise Exception('Incorrect value of outputIndex for UTXO %s' %
                                str(idx))

            trusted_input = self.chip.getTrustedInput(prev_transaction,
                                                      utxo_tx_index)
            self.trusted_inputs.append(trusted_input)

            # Hash check
            curr_pubkey = compress_public_key(
                self.chip.getWalletPublicKey(bip32_path)['publicKey'])
            pubkey_hash = bin_hash160(curr_pubkey)
            pubkey_hash_from_script = extract_pkh_from_locking_script(
                prev_transaction.outputs[utxo_tx_index].script)
            if pubkey_hash != pubkey_hash_from_script:
                text = "Error: different public key hashes for the BIP32 path and the UTXO"
                text += "locking script. Your signed transaction will not be validated by the network.\n"
                text += "pubkey_hash: %s\n" % str(pubkey_hash)
                text += "pubkey_hash_from_script: %s\n" % str(
                    pubkey_hash_from_script)
                printDbg(text)

            self.arg_inputs.append({
                'locking_script':
                prev_transaction.outputs[utxo['tx_ouput_n']].script,
                'pubkey':
                curr_pubkey,
                'bip32_path':
                bip32_path,
                'outputIndex':
                utxo['tx_ouput_n'],
                'txid':
                utxo['tx_hash']
            })

        self.amount -= int(tx_fee)
        self.amount = int(self.amount)
        arg_outputs = [{
            'address': dest_address,
            'valueSat': self.amount
        }]  # there will be multiple outputs soon
        self.new_transaction = bitcoinTransaction(
        )  # new transaction object to be used for serialization at the last stage
        self.new_transaction.version = bytearray([0x01, 0x00, 0x00, 0x00])

        try:
            for o in arg_outputs:
                output = bitcoinOutput()
                output.script = compose_tx_locking_script(o['address'])
                output.amount = int.to_bytes(o['valueSat'],
                                             8,
                                             byteorder='little')
                self.new_transaction.outputs.append(output)
        except Exception:
            raise

        # join all outputs - will be used by Ledger for signing transaction
        self.all_outputs_raw = self.new_transaction.serializeOutputs()

        self.mBox2 = QMessageBox(caller)
        messageText = "Check display of your hardware device<br><br><br>"
        messageText += "From bip32_path: <b>%s</b><br><br>" % str(bip32_path)
        messageText += "To PIVX Address: <b>%s</b><br><br>" % dest_address
        messageText += "PIV amount: <b>%s</b><br>" % str(
            round(self.amount / 1e8, 8))
        messageText += "plus PIV for fee: <b>%s</b><br><br>" % str(
            round(int(tx_fee) / 1e8, 8))
        self.mBox2.setText(messageText)
        self.mBox2.setIconPixmap(
            caller.tabMain.ledgerImg.scaledToHeight(200,
                                                    Qt.SmoothTransformation))
        self.mBox2.setWindowTitle("CHECK YOUR LEDGER")
        self.mBox2.setStandardButtons(QMessageBox.NoButton)
        self.mBox2.setMaximumWidth(500)
        self.mBox2.show()

        ThreadFuns.runInThread(self.signTxSign, (), self.signTxFinish)
Ejemplo n.º 19
0
    utxo_tx_index = utxo['outputIndex']
    if utxo_tx_index < 0 or utxo_tx_index > len(prev_transaction.outputs):
        raise Exception('Incorrent value of outputIndex for UTXO %s' %
                        str(idx))

    trusted_input = app.getTrustedInput(prev_transaction, utxo_tx_index)
    trusted_inputs.append(trusted_input)

    bip32path = utxo['bip32_path']
    pubkey = bip32_to_address.get(bip32path)
    if not pubkey:
        pubkey = compress_public_key(
            app.getWalletPublicKey(bip32path)['publicKey'])
        bip32_to_address[bip32path] = pubkey
    pubkey_hash = bitcoin.bin_hash160(pubkey)

    # verify if the public key hash of the wallet's bip32 path is the same as specified in the UTXO locking script
    # if they differ, signature and public key we produce and are going to include in the unlocking script won't
    # match the locking script conditions - transaction will be rejected by the network
    pubkey_hash_from_script = extract_pkh_from_locking_script(
        prev_transaction.outputs[utxo_tx_index].script)
    if pubkey_hash != pubkey_hash_from_script:
        print(
            "Error: different public key hashes for the BIP32 path %s (UTXO %s) and the UTXO locking script. Your "
            "signed transaction will not be validated by the network." %
            (bip32path, str(idx)))

    arg_inputs.append({
        'locking_script':
        prev_transaction.outputs[utxo['outputIndex']].script,
Ejemplo n.º 20
0
    def signTx(self, device, bip32_path, utxos_to_spend, dest_address, tx_fee,
               rawtransactions):
        # For each UTXO create a Ledger 'trusted input'
        self.trusted_inputs = []
        #    https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand)
        self.arg_inputs = []

        self.amount = 0
        for idx, utxo in enumerate(utxos_to_spend):

            self.amount += int(utxo['value'])

            raw_tx = bytearray.fromhex(rawtransactions[utxo['tx_hash']])

            if not raw_tx:
                raise Exception("Can't find raw transaction for txid: " +
                                rawtransactions[utxo['tx_hash']])

            # parse the raw transaction, so that we can extract the UTXO locking script we refer to
            prev_transaction = bitcoinTransaction(raw_tx)

            utxo_tx_index = utxo['tx_ouput_n']
            if utxo_tx_index < 0 or utxo_tx_index > len(
                    prev_transaction.outputs):
                raise Exception('Incorrect value of outputIndex for UTXO %s' %
                                str(idx))

            trusted_input = self.device.chip.getTrustedInput(
                prev_transaction, utxo_tx_index)
            self.trusted_inputs.append(trusted_input)

            # Hash check
            curr_pubkey = compress_public_key(
                device.chip.getWalletPublicKey(bip32_path)['publicKey'])
            pubkey_hash = bin_hash160(curr_pubkey)
            pubkey_hash_from_script = extract_pkh_from_locking_script(
                prev_transaction.outputs[utxo_tx_index].script)
            if pubkey_hash != pubkey_hash_from_script:
                text = "Error: different public key hashes for the BIP32 path and the UTXO"
                text += "locking script. Your signed transaction will not be validated by the network.\n"
                text += "pubkey_hash: %s\n" % str(pubkey_hash)
                text += "pubkey_hash_from_script: %s\n" % str(
                    pubkey_hash_from_script)
                print(text)

            self.arg_inputs.append({
                'locking_script':
                prev_transaction.outputs[utxo['tx_ouput_n']].script,
                'pubkey':
                curr_pubkey,
                'bip32_path':
                bip32_path,
                'outputIndex':
                utxo['tx_ouput_n'],
                'txid':
                utxo['tx_hash']
            })

        self.amount -= int(tx_fee)
        self.amount = int(self.amount)
        arg_outputs = [{
            'address': dest_address,
            'valueSat': self.amount
        }]  # there will be multiple outputs soon
        self.new_transaction = bitcoinTransaction(
        )  # new transaction object to be used for serialization at the last stage
        self.new_transaction.version = bytearray([0x01, 0x00, 0x00, 0x00])
        try:
            for o in arg_outputs:
                output = bitcoinOutput()
                output.script = compose_tx_locking_script(o['address'])
                output.amount = int.to_bytes(o['valueSat'],
                                             8,
                                             byteorder='little')
                self.new_transaction.outputs.append(output)
        except Exception:
            raise
        # join all outputs - will be used by Ledger for signing transaction
        self.all_outputs_raw = self.new_transaction.serializeOutputs()

        starting = True
        # sign all inputs on Ledger and add inputs in the self.new_transaction object for serialization
        for idx, new_input in enumerate(self.arg_inputs):
            device.chip.startUntrustedTransaction(starting, idx,
                                                  self.trusted_inputs,
                                                  new_input['locking_script'])

            device.chip.finalizeInputFull(self.all_outputs_raw)

            sig = device.chip.untrustedHashSign(new_input['bip32_path'],
                                                lockTime=0)

            new_input['signature'] = sig
            inputTx = bitcoinInput()
            inputTx.prevOut = bytearray.fromhex(
                new_input['txid'])[::-1] + int.to_bytes(
                    new_input['outputIndex'], 4, byteorder='little')

            inputTx.script = bytearray([len(sig)]) + sig + bytearray(
                [0x21]) + new_input['pubkey']

            inputTx.sequence = bytearray([0xFF, 0xFF, 0xFF, 0xFF])

            self.new_transaction.inputs.append(inputTx)

            starting = False

            self.new_transaction.lockTime = bytearray([0, 0, 0, 0])
            self.tx_raw = bytearray(self.new_transaction.serialize())

        if self.tx_raw is not None:
            return (self.tx_raw, str(round(self.amount / 1e8, 8)))
        else:
            # transaction refused by user
            return (None, "")
Ejemplo n.º 21
0
    def prepare_transfer_tx_bulk(self, caller, mnodes, dest_address, tx_fee, rawtransactions, useSwiftX=False):
        # For each UTXO create a Ledger 'trusted input'
        self.trusted_inputs = []
        #    https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand)
        self.arg_inputs = []
        self.amount = 0
        self.lock.acquire()
        num_of_sigs = sum([len(mnode['utxos']) for mnode in mnodes])
        curr_utxo_checked = 0
        try:
            for i, mnode in enumerate(mnodes): 
                
                for idx, utxo in enumerate(mnode['utxos']):
                                       
                    self.amount += int(utxo['value'])
                    raw_tx = bytearray.fromhex(rawtransactions[utxo['tx_hash']])
    
                    if not raw_tx:
                        raise Exception("Can't find raw transaction for txid: " + rawtransactions[utxo['tx_hash']])
                
                    # parse the raw transaction, so that we can extract the UTXO locking script we refer to
                    prev_transaction = bitcoinTransaction(raw_tx)
    
                    utxo_tx_index = utxo['tx_ouput_n']
                    if utxo_tx_index < 0 or utxo_tx_index > len(prev_transaction.outputs):
                        raise Exception('Incorrect value of outputIndex for UTXO %s' % str(idx))
                
                
                    trusted_input = self.chip.getTrustedInput(prev_transaction, utxo_tx_index)
                    self.trusted_inputs.append(trusted_input)
               
                    # Hash check
                    curr_pubkey = compress_public_key(self.chip.getWalletPublicKey(mnode['path'])['publicKey'])
                    pubkey_hash = bin_hash160(curr_pubkey)
                    pubkey_hash_from_script = extract_pkh_from_locking_script(prev_transaction.outputs[utxo_tx_index].script)
                    if pubkey_hash != pubkey_hash_from_script:
                        text = "Error: The hashes for the public key for the BIP32 path, and the UTXO locking script do not match."
                        text += "Your signed transaction will not be validated by the network.\n"
                        text += "pubkey_hash: %s\n" % pubkey_hash.hex()
                        text += "pubkey_hash_from_script: %s\n" % pubkey_hash_from_script.hex()
                        printDbg(text)
    
                    self.arg_inputs.append({
                        'locking_script': prev_transaction.outputs[utxo['tx_ouput_n']].script,
                        'pubkey': curr_pubkey,
                        'bip32_path': mnode['path'],
                        'outputIndex': utxo['tx_ouput_n'],
                        'txid': utxo['tx_hash']
                    })
                    
                    # completion percent emitted
                    curr_utxo_checked += 1
                    completion = int(95*curr_utxo_checked / num_of_sigs)
                    self.tx_progress.emit(completion)
    
            self.amount -= int(tx_fee)
            self.amount = int(self.amount)
            arg_outputs = [{'address': dest_address, 'valueSat': self.amount}] # there will be multiple outputs soon
            self.new_transaction = bitcoinTransaction()  # new transaction object to be used for serialization at the last stage
            self.new_transaction.version = bytearray([0x01, 0x00, 0x00, 0x00])
            
            self.tx_progress.emit(99)
            
        except Exception:
            raise
        
        finally:
            self.lock.release()
        
        try:
            for o in arg_outputs:
                output = bitcoinOutput()
                output.script = compose_tx_locking_script(o['address'])
                output.amount = int.to_bytes(o['valueSat'], 8, byteorder='little')
                self.new_transaction.outputs.append(output)
        except Exception:
            raise
    
        self.tx_progress.emit(100)
        
        # join all outputs - will be used by Ledger for signing transaction
        self.all_outputs_raw = self.new_transaction.serializeOutputs()

        self.mBox2 = QMessageBox(caller)
        self.messageText = "<p>Confirm transaction on your device, with the following details:</p>"
        #messageText += "From bip32_path: <b>%s</b><br><br>" % str(bip32_path)
        self.messageText += "<p>Payment to:<br><b>%s</b></p>" % dest_address
        self.messageText += "<p>Net amount:<br><b>%s</b> PIV</p>" % str(round(self.amount / 1e8, 8))
        if useSwiftX:
            self.messageText += "<p>Fees (SwiftX flat rate):<br><b>%s</b> PIV<p>" % str(round(int(tx_fee) / 1e8, 8))
        else:
            self.messageText += "<p>Fees:<br><b>%s</b> PIV<p>" % str(round(int(tx_fee) / 1e8, 8))
        messageText = self.messageText + "Signature Progress: 0 %" 
        self.mBox2.setText(messageText)
        self.mBox2.setIconPixmap(caller.tabMain.ledgerImg.scaledToHeight(200, Qt.SmoothTransformation))
        self.mBox2.setWindowTitle("CHECK YOUR LEDGER")
        self.mBox2.setStandardButtons(QMessageBox.NoButton)
        self.mBox2.setMaximumWidth(500)
        self.mBox2.show()
                
        ThreadFuns.runInThread(self.signTxSign, (), self.signTxFinish)