Esempio n. 1
0
    def _xpriv_to_xpub(xpriv: str) -> str:
        '''
        Turns an xpriv into an xpub.
        Args:
            xpriv (str): the b58 encoded xpriv
        Returns:
        '''
        xpub = bytearray()
        xpriv_bytes = base58.decode(xpriv)

        # determine what network the key is on
        if xpriv_bytes[0:4] == utils.VERSION_BYTES['mainnet']['private']:
            # mainnet
            xpub.extend(utils.VERSION_BYTES['mainnet']['public'])
        elif xpriv_bytes[0:4] == utils.VERSION_BYTES['testnet'][
                'private']:  # pragma: nocover  # noqa: E501
            # testnet
            xpub.extend(utils.VERSION_BYTES['testnet']
                        ['public'])  # pragma: nocover  # noqa: E501
        else:
            raise ValueError('unrecognized version bytes. '
                             'Is this an xpub?')  # pragma: nocover

        # most parts are verbatim
        xpub.extend(xpriv_bytes[4:45])

        # derive the pubkey and append it
        xpub.extend(simple.priv_to_pub(xpriv_bytes[46:78]))

        return base58.encode(xpub)
Esempio n. 2
0
    def _child_from_xpriv(self, index: int, child_xpriv: str) -> 'HDKey':
        '''
        Returns a new HDKey object based on the current object and the new
            child xpriv. Don't call this directly, it's for child derivation.
        Args:
            index       (int): the index of the child
            child_xpriv (str): the child's xpriv
        Returns
            HDKey: the new child object
        '''
        # set the path, if this key has a path
        path: Optional[str]
        if self.path is not None:
            if index >= utils.BIP32_HARDEN:
                index_str = '{}h'.format(str(index - utils.BIP32_HARDEN))
            else:
                index_str = str(index)
            path = '{}/{}'.format(self.path, index_str)
        else:
            path = None

        # Make the pubkey
        xpriv_bytes = base58.decode(child_xpriv)
        privkey = xpriv_bytes[46:78]
        pubkey = simple.priv_to_pub(privkey)

        # What network is this for?
        if xpriv_bytes[0:4] == utils.VERSION_BYTES['mainnet']['private']:
            network = 'Bitcoin'
        elif xpriv_bytes[0:4] == utils.VERSION_BYTES['testnet'][
                'private']:  # pragma: nocover  # noqa: E501
            network = 'Testnet'  # pragma: nocover
        else:
            raise ValueError('unrecognized version bytes. '
                             'Is this an xpriv?')  # pragma: nocover

        return HDKey(key_dict=KeyDict(path=path,
                                      network=network,
                                      depth=xpriv_bytes[4],
                                      parent_fingerprint=xpriv_bytes[5:9],
                                      index=index,
                                      parent=self,
                                      chain_code=xpriv_bytes[13:45],
                                      fingerprint=utils.hash160(pubkey)[:4],
                                      xpriv=child_xpriv,
                                      xpub=HDKey._xpriv_to_xpub(child_xpriv),
                                      privkey=privkey,
                                      pubkey=pubkey),
                     _error_on_call=False)
Esempio n. 3
0
 def _make_child_xpub(self, child_pubkey: bytes, index: int,
                      chain_code: bytes) -> str:
     '''
     Makes a child xpub based on the current key and the child key info.
     Args:
         child_pubkey (bytes): the child pubkey
         index          (int): the child index
         chain_code   (bytes): the child chain code
     Returns
         (str): the child xpub
     '''
     xpub = bytearray()
     xpub.extend(base58.decode(cast(str, self.xpub))[0:4])  # prefix
     xpub.extend([cast(int, self.depth) + 1])  # depth
     xpub.extend(self.fingerprint)  # fingerprint
     xpub.extend(index.to_bytes(4, byteorder='big'))  # index
     xpub.extend(chain_code)  # chain_code
     xpub.extend(child_pubkey)  # pubkey (comp)
     return base58.encode(xpub)
Esempio n. 4
0
    def _child_from_xpub(self, index: int, child_xpub: str) -> 'HDKey':
        '''
        Returns a new HDKey object based on the current object and the new
            child xpub. Don't call this directly, it's for child derivation.
        Args:
            index      (int): the index of the child
            child_xpub (str): the child's xpub
        Returns
            HDKey: the new child object
        '''
        path: Optional[str]
        if self.path is not None:
            path = '{}/{}'.format(self.path, str(index))
        else:
            path = None
        xpub_bytes = base58.decode(child_xpub)
        pubkey = xpub_bytes[45:78]

        if xpub_bytes[0:4] == utils.VERSION_BYTES['mainnet']['public']:
            network = 'Bitcoin'
        elif xpub_bytes[0:4] == utils.VERSION_BYTES['testnet'][
                'public']:  # pragma: nocover  # noqa: E501
            network = 'Testnet'  # pragma: nocover
        else:
            raise ValueError('unrecognized version bytes.'
                             ' Is this an xpub?')  # pragma: nocover

        return HDKey(key_dict=KeyDict(path=path,
                                      network=network,
                                      depth=xpub_bytes[4],
                                      parent_fingerprint=xpub_bytes[5:9],
                                      index=int.from_bytes(xpub_bytes[9:13],
                                                           byteorder='big'),
                                      parent=self,
                                      chain_code=xpub_bytes[13:45],
                                      fingerprint=utils.hash160(pubkey)[:4],
                                      xpriv=None,
                                      xpub=child_xpub,
                                      privkey=None,
                                      pubkey=pubkey),
                     _error_on_call=False)
Esempio n. 5
0
    def from_xpub(HDKey, xpub: str, path: Optional[str] = None) -> 'HDKey':
        '''
        Instantiate an HDKey from an xpub. Populates all possible fields
        Args:
            xpub (str): the xpub
            path (str): the path if it's known. useful for calling derive_path
        Returns:
            (HDKey): the key object
        '''
        xpub_bytes = base58.decode(xpub)
        pubkey = xpub_bytes[45:78]
        try:
            simple.compress_pubkey(pubkey)
        except Exception:
            raise ValueError('Cannot parse public key')

        if xpub_bytes[0:4] == utils.VERSION_BYTES['mainnet']['public']:
            network = 'Bitcoin'
        elif xpub_bytes[0:4] == utils.VERSION_BYTES['testnet'][
                'public']:  # pragma: nocover  # noqa: E501
            network = 'Testnet'  # pragma: nocover
        else:
            raise ValueError('unrecognized version bytes. Is this an xpub?'
                             )  # pragma: nocover  # noqa: E501

        return HDKey(key_dict=KeyDict(path=path,
                                      network=network,
                                      depth=xpub_bytes[4],
                                      parent_fingerprint=xpub_bytes[5:9],
                                      index=int.from_bytes(xpub_bytes[9:13],
                                                           byteorder='big'),
                                      parent=None,
                                      chain_code=xpub_bytes[13:45],
                                      fingerprint=utils.hash160(pubkey)[:4],
                                      xpriv=None,
                                      xpub=xpub,
                                      privkey=None,
                                      pubkey=pubkey),
                     _error_on_call=False)