Exemplo n.º 1
0
    def signTxSign(self, ctrl):
        self.tx_raw = None
        with self.lock:
            starting = True
            curr_input_signed = 0
            # 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):
                   
                self.chip.startUntrustedTransaction(starting, idx, self.trusted_inputs, new_input['locking_script'])
                 
                self.chip.finalizeInputFull(self.all_outputs_raw)
                
                sig = self.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
                
                # signature percent emitted
                curr_input_signed += 1
                completion = int(100*curr_input_signed / len(self.arg_inputs))
                self.sig_progress.emit(completion)
                
            self.new_transaction.lockTime = bytearray([0, 0, 0, 0])
            self.tx_raw = bytearray(self.new_transaction.serialize())
            self.sig_progress.emit(100)
Exemplo n.º 2
0
    def signTxSign(self, ctrl):
        self.lock.acquire()
        try:
            starting = True
            curr_input_signed = 0
            # 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):
                   
                self.chip.startUntrustedTransaction(starting, idx, self.trusted_inputs, new_input['locking_script'])
                 
                self.chip.finalizeInputFull(self.all_outputs_raw)
                
                sig = self.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
                
                # signature percent emitted
                curr_input_signed += 1
                completion = int(100*curr_input_signed / len(self.arg_inputs))
                self.sig_progress.emit(completion)
                
            self.new_transaction.lockTime = bytearray([0, 0, 0, 0])
            self.tx_raw = bytearray(self.new_transaction.serialize())
            self.sig_progress.emit(100)
            
        except TypeError as te:
            printDbg(str(te))
            self.tx_raw = None
            
        except Exception as e:
            if e.sw != 0x6985:
                self.status = 0
                printException(getCallerName(), getFunctionName(), e.message, e.args)            
            self.tx_raw = None
            
        finally:
            self.lock.release()
            if self.status == 0:
                self.dongle.close()
                self.initDevice()
Exemplo n.º 3
0
    def signTxSign(self, ctrl):
        self.lock.acquire()
        try:
            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):
                self.chip.startUntrustedTransaction(
                    starting, idx, self.trusted_inputs,
                    new_input['locking_script'])

                self.chip.finalizeInputFull(self.all_outputs_raw)

                sig = self.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())

        except Exception as e:
            printException(getCallerName(), getFunctionName(),
                           "Signature Exception", e.args)
            self.tx_raw = None

        finally:
            self.lock.release()
Exemplo n.º 4
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, "")