Ejemplo n.º 1
0
    def tx_inputs(self, tx: Transaction,
                  xpub_path: Dict[str, str]) -> List[types.TxInputType]:
        inputs = []
        for txin in tx.inputs:
            txinputtype = types.TxInputType()

            x_pubkeys = txin.x_pubkeys
            if len(x_pubkeys) == 1:
                x_pubkey = x_pubkeys[0]
                xpub, path = x_pubkey.bip32_extended_key_and_path()
                xpub_n = bip32_decompose_chain_string(xpub_path[xpub])
                txinputtype.address_n.extend(xpub_n)
                txinputtype.address_n.extend(path)
                txinputtype.script_type = types.SPENDADDRESS
            else:

                def f(x_pubkey):
                    if x_pubkey.is_bip32_key():
                        xpub, path = x_pubkey.bip32_extended_key_and_path()
                    else:
                        xpub = BIP32PublicKey(x_pubkey.to_public_key(),
                                              NULL_DERIVATION, Net.COIN)
                        xpub = xpub.to_extended_key_string()
                        path = []
                    node = keepkeylib.ckd_public.deserialize(xpub)
                    return types.HDNodePathType(node=node, address_n=path)

                pubkeys = [f(x) for x in x_pubkeys]
                multisig = types.MultisigRedeemScriptType(
                    pubkeys=pubkeys,
                    signatures=txin.stripped_signatures_with_blanks(),
                    m=txin.threshold,
                )
                script_type = types.SPENDMULTISIG
                txinputtype = types.TxInputType(script_type=script_type,
                                                multisig=multisig)
                # find which key is mine
                for x_pubkey in x_pubkeys:
                    if x_pubkey.is_bip32_key():
                        xpub, path = x_pubkey.bip32_extended_key_and_path()
                        if xpub in xpub_path:
                            xpub_n = tuple(
                                bip32_decompose_chain_string(xpub_path[xpub]))
                            txinputtype.address_n.extend(xpub_n)
                            txinputtype.address_n.extend(path)
                            break

            txinputtype.prev_hash = bytes(reversed(txin.prev_hash))
            txinputtype.prev_index = txin.prev_idx
            txinputtype.sequence = txin.sequence
            txinputtype.amount = txin.value

            inputs.append(txinputtype)

        return inputs
Ejemplo n.º 2
0
    def tx_outputs(self, keystore: KeepKey_KeyStore, derivation: str,
                   tx: Transaction):
        has_change = False
        account_derivation = tuple(bip32_decompose_chain_string(derivation))
        keystore_fingerprint = keystore.get_fingerprint()

        outputs = []
        assert tx.output_info is not None
        for tx_output, output_metadatas in zip(tx.outputs, tx.output_info):
            info = output_metadatas.get(keystore_fingerprint)
            if info is not None and not has_change:
                has_change = True  # no more than one change address
                key_derivation, xpubs, m = info
                if len(xpubs) == 1:
                    script_type = types.PAYTOADDRESS
                    txoutputtype = types.TxOutputType(
                        amount=tx_output.value,
                        script_type=script_type,
                        address_n=account_derivation + key_derivation,
                    )
                else:
                    script_type = types.PAYTOMULTISIG
                    nodes = [
                        keepkeylib.ckd_public.deserialize(xpub)
                        for xpub in xpubs
                    ]
                    pubkeys = [
                        types.HDNodePathType(node=node,
                                             address_n=key_derivation)
                        for node in nodes
                    ]
                    multisig = types.MultisigRedeemScriptType(
                        pubkeys=pubkeys, signatures=[b''] * len(pubkeys), m=m)
                    txoutputtype = types.TxOutputType(
                        multisig=multisig,
                        amount=tx_output.value,
                        address_n=account_derivation + key_derivation,
                        script_type=script_type)
            else:
                txoutputtype = types.TxOutputType()
                txoutputtype.amount = tx_output.value
                address = classify_tx_output(tx_output)
                if isinstance(address, Address):
                    txoutputtype.script_type = types.PAYTOADDRESS
                    txoutputtype.address = address.to_string()

            outputs.append(txoutputtype)

        return outputs
Ejemplo n.º 3
0
    def tx_inputs(self, tx, for_sig=False):
        inputs = []
        for txin in tx.inputs:
            txinputtype = types.TxInputType()
            if txin.get('is_coinbase'):
                prev_hash = "\0" * 32
                prev_index = 0xffffffff  # signed int -1
            else:
                if for_sig:
                    x_pubkeys = txin['x_pubkeys']
                    if len(x_pubkeys) == 1:
                        x_pubkey = x_pubkeys[0]
                        xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
                        xpub_n = self.get_client().expand_path(
                            self.xpub_path[xpub])
                        txinputtype.address_n.extend(xpub_n + s)
                    else:

                        def f(x_pubkey):
                            if is_extended_pubkey(x_pubkey):
                                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
                            else:
                                xpub = xpub_from_pubkey(x_pubkey.decode('hex'))
                                s = []
                            node = ckd_public.deserialize(xpub)
                            return types.HDNodePathType(node=node, address_n=s)

                        pubkeys = map(f, x_pubkeys)
                        multisig = types.MultisigRedeemScriptType(
                            pubkeys=pubkeys,
                            signatures=map(
                                lambda x: x.decode('hex') if x else '',
                                txin.get('signatures')),
                            m=txin.get('num_sig'),
                        )
                        txinputtype = types.TxInputType(
                            script_type=types.SPENDMULTISIG, multisig=multisig)
                        # find which key is mine
                        for x_pubkey in x_pubkeys:
                            xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
                            if xpub in self.xpub_path:
                                xpub_n = self.get_client().expand_path(
                                    self.xpub_path[xpub])
                                txinputtype.address_n.extend(xpub_n + s)
                                break
                            else:
                                raise

                prev_hash = unhexlify(txin['prevout_hash'])
                prev_index = txin['prevout_n']

            txinputtype.prev_hash = prev_hash
            txinputtype.prev_index = prev_index

            if 'scriptSig' in txin:
                script_sig = txin['scriptSig'].decode('hex')
                txinputtype.script_sig = script_sig

            if 'sequence' in txin:
                sequence = txin['sequence']
                txinputtype.sequence = sequence

            inputs.append(txinputtype)

        return inputs