Exemplo n.º 1
0
    def display_singlesig_address(
        self,
        keypath: str,
        addr_type: AddressType,
    ) -> str:
        self._check_unlocked()

        # Script type
        if addr_type == AddressType.SH_WIT:
            script_type = messages.InputScriptType.SPENDP2SHWITNESS
        elif addr_type == AddressType.WIT:
            script_type = messages.InputScriptType.SPENDWITNESS
        elif addr_type == AddressType.LEGACY:
            script_type = messages.InputScriptType.SPENDADDRESS
        else:
            raise BadArgumentError("Unknown address type")

        expanded_path = parse_path(keypath)

        try:
            address = btc.get_address(
                self.client,
                self.coin_name,
                expanded_path,
                show_display=True,
                script_type=script_type,
                multisig=None,
            )
            assert isinstance(address, str)
            return address
        except Exception:
            pass

        raise BadArgumentError("No path supplied matched device keys")
Exemplo n.º 2
0
 def display_singlesig_address(self, bip32_path: str, addr_type: AddressType) -> str:
     path = parse_path(bip32_path)
     addr_type = self._convertAddrType(addr_type)
     address = self.jade.get_receive_address(
         self._network(), path, variant=addr_type
     )
     return address
Exemplo n.º 3
0
 def get_pubkey_at_path(self, path: str) -> ExtendedKey:
     self._check_unlocked()
     try:
         expanded_path = parse_path(path)
     except ValueError as e:
         raise BadArgumentError(str(e))
     output = btc.get_public_node(
         self.client, expanded_path, coin_name=self.coin_name
     )
     xpub = ExtendedKey.deserialize(output.xpub)
     if self.chain != Chain.MAIN:
         xpub.version = ExtendedKey.TESTNET_PUBLIC
     return xpub
Exemplo n.º 4
0
    def test_deriv_path(self):
        for test in self.data["deriv_path"]:
            with self.subTest(test=test):
                # Deser
                par_xpub = ExtendedKey.deserialize(test["parent_xpub"])
                par_xprv = ExtendedKey.deserialize(test["parent_xprv"])

                # Parse the path
                path = parse_path(test["path"])

                # Derive
                child_xpub = test["child_xpub"]
                xpub_der = par_xpub.derive_pub_path(path)
                self.assertEqual(xpub_der.to_string(), child_xpub)
                xprv_der = par_xprv.derive_pub_path(path)
                self.assertEqual(xprv_der.to_string(), child_xpub)
Exemplo n.º 5
0
    def display_multisig_address(
        self,
        addr_type: AddressType,
        multisig: MultisigDescriptor,
    ) -> str:
        self._check_unlocked()

        der_pks = list(
            zip([p.get_pubkey_bytes(0) for p in multisig.pubkeys], multisig.pubkeys)
        )
        if multisig.is_sorted:
            der_pks = sorted(der_pks)

        pubkey_objs = []
        for pk, p in der_pks:
            if p.extkey is not None:
                xpub = p.extkey
                hd_node = messages.HDNodeType(
                    depth=xpub.depth,
                    fingerprint=int.from_bytes(xpub.parent_fingerprint, "big"),
                    child_num=xpub.child_num,
                    chain_code=xpub.chaincode,
                    public_key=xpub.pubkey,
                )
                pubkey_objs.append(
                    messages.HDNodePathType(
                        node=hd_node,
                        address_n=parse_path(
                            "m" + p.deriv_path if p.deriv_path is not None else ""
                        ),
                    )
                )
            else:
                hd_node = messages.HDNodeType(
                    depth=0,
                    fingerprint=0,
                    child_num=0,
                    chain_code=b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
                    public_key=pk,
                )
                pubkey_objs.append(messages.HDNodePathType(node=hd_node, address_n=[]))

        trezor_ms = messages.MultisigRedeemScriptType(
            m=multisig.thresh, signatures=[b""] * len(pubkey_objs), pubkeys=pubkey_objs
        )

        # Script type
        if addr_type == AddressType.SH_WIT:
            script_type = messages.InputScriptType.SPENDP2SHWITNESS
        elif addr_type == AddressType.WIT:
            script_type = messages.InputScriptType.SPENDWITNESS
        elif addr_type == AddressType.LEGACY:
            script_type = messages.InputScriptType.SPENDMULTISIG
        else:
            raise BadArgumentError("Unknown address type")

        for p in multisig.pubkeys:
            keypath = p.origin.get_derivation_path() if p.origin is not None else "m/"
            keypath += p.deriv_path if p.deriv_path is not None else ""
            path = parse_path(keypath)
            try:
                address = btc.get_address(
                    self.client,
                    self.coin_name,
                    path,
                    show_display=True,
                    script_type=script_type,
                    multisig=trezor_ms,
                )
                assert isinstance(address, str)
                return address
            except Exception:
                pass

        raise BadArgumentError("No path supplied matched device keys")
Exemplo n.º 6
0
 def sign_message(self, message: Union[str, bytes], keypath: str) -> str:
     self._check_unlocked()
     path = parse_path(keypath)
     result = btc.sign_message(self.client, self.coin_name, path, message)
     return base64.b64encode(result.signature).decode("utf-8")
Exemplo n.º 7
0
    def display_multisig_address(
        self,
        addr_type: AddressType,
        multisig: MultisigDescriptor,
    ) -> str:
        signer_origins = []
        signers = []
        paths = []
        for pubkey in multisig.pubkeys:
            if pubkey.extkey is None:
                raise BadArgumentError(
                    "Blockstream Jade can only generate addresses for multisigs with full extended keys"
                )
            if pubkey.origin is None:
                raise BadArgumentError(
                    "Blockstream Jade can only generate addresses for multisigs with key origin information"
                )
            if pubkey.deriv_path is None:
                raise BadArgumentError(
                    "Blockstream Jade can only generate addresses for multisigs with key origin derivation path information"
                )

            # Tuple to derive deterministic name for the registrtion
            signer_origins.append((pubkey.origin.fingerprint, pubkey.origin.path))

            #  We won't include the additional path in the multisig registration
            signers.append(
                {
                    "fingerprint": pubkey.origin.fingerprint,
                    "derivation": pubkey.origin.path,
                    "xpub": pubkey.pubkey,
                    "path": [],
                }
            )

            # Instead hold it as the address path
            path = (
                pubkey.deriv_path[1:]
                if pubkey.deriv_path[0] == "/"
                else pubkey.deriv_path
            )
            paths.append(parse_path(path))

        # sort origins, signers and paths according to origins (like in _get_multisig_name)
        signer_origins, signers, paths = [
            list(a) for a in zip(*sorted(zip(signer_origins, signers, paths)))
        ]

        # Get a deterministic name for this multisig wallet
        script_variant = self._convertAddrType(addr_type, multisig=True)
        multisig_name = self._get_multisig_name(
            script_variant, multisig.thresh, signer_origins
        )

        # Need to ensure this multisig wallet is registered first
        # (Note: 're-registering' is a no-op)
        self.jade.register_multisig(
            self._network(),
            multisig_name,
            script_variant,
            True,  # always use sorted
            multisig.thresh,
            signers,
        )
        address = self.jade.get_receive_address(
            self._network(), paths, multisig_name=multisig_name
        )

        return str(address)
Exemplo n.º 8
0
 def sign_message(self, message: Union[str, bytes], bip32_path: str) -> str:
     path = parse_path(bip32_path)
     if isinstance(message, bytes) or isinstance(message, bytearray):
         message = message.decode("utf-8")
     signature = self.jade.sign_message(path, message)
     return signature
Exemplo n.º 9
0
 def get_pubkey_at_path(self, bip32_path: str) -> ExtendedKey:
     path = parse_path(bip32_path)
     xpub = self.jade.get_xpub(self._network(), path)
     ext_key = ExtendedKey.deserialize(xpub)
     return ext_key