def test_is_xpublic_key_valid(): assert is_xpublic_key_valid( decode_base58( "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtK" "x6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True)) == True assert is_xpublic_key_valid( "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakF" "pxHwNyXDSmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2") == True assert is_xpublic_key_valid( "ypub6TZ8XHFAAptgVqYk8TMc2rqJrqVYYJwYnyinkpsLSJviSfRfzta" "Sx1kihDCsndWJYY6xEqmLaHFraTwDok8knAgrG1ipNwuwtdakQibcvzB") == True assert is_xpublic_key_valid( "upub57Wa4MvRPNyAivfs3RdRnBNn6jhkarina5xLFiBMvCH4NVqWUPQU" "pKeh5KZfvYXDyYXStKeUzhrMcQt4p9upL1pW2EFdY8eMJjPA8UKuxaL") == True assert is_xpublic_key_valid( "zpub6nPPpwv5KWSAM8jrxp9EEwvp2odzUvw3i6F1YDmDpKJbVmEuFYk" "1a5QriRATnYADxBDkzKMu2wcQTkYnXSYmaQNT8MRExrjSAMePoDv2d2R") == True assert is_xpublic_key_valid( "vpub5SLqN2bLY4WeaDrysnR3zGUHGhrCXUiHVCUZ375FJCewRbejj3a3" "SPJq6XXFvTB9PBeFdoF3TNCuVhVdXrKq8FW6tZx483TqaTSoWx3U88j") == True assert is_xpublic_key_valid( decode_base58( "vpuc5SLqN2bLY4WeaDrysnR3zGUHGhrCXUiHVCUZ375FJCewRbejj3a3" "SPJq6XXFvTB9PBeFdoF3TNCuVhVdXrKq8FW6tZx483TqaTSoWx3U88j", checksum=True)) == False assert is_xpublic_key_valid( "qpub5SLqN2bLY4WeaDrysnR3zGUHGhrCXUiHVCUZ375FJCewRbejj3a3SPJq6XXFvTB9PBeFdoF3TNCuVhVdXrKq8FW6tZx483TqaTSoWx3U88j" ) == False assert is_xpublic_key_valid("") == False assert is_xpublic_key_valid("1212qsdbfnn,i;p/") == False
def test_derive_xkey(): root = "xprv9s21ZrQH143K39fFeGf2cWBTZ6NVj6ZsQ7nEK9f5pWqt4YwHPhnC" \ "F3GtMsPNA9cCz1j8j9Zs493ejkzJqUWqwGqQ2J8iNc1jFtFPbie7bZ4" assert derive_xkey(decode_base58(root, checksum=True), "m/0") == "xprv9v7aNJTyjf9pZ2e1XwaKwTaiYqmwy9C43GPrczk9NauP4aWYqeKh" \ "5UfE3ocfV92UGFKBbQNZib8TDtqD8y5axYQMUzVJzHXphdNF6Cc6YM3" assert derive_xkey(root, decode_path("m/0")) == "xprv9v7aNJTyjf9pZ2e1XwaKwTaiYqmwy9C43GPrczk9NauP4aWYqeKh" \ "5UfE3ocfV92UGFKBbQNZib8TDtqD8y5axYQMUzVJzHXphdNF6Cc6YM3" assert derive_xkey(root, "m/0'") == "xprv9v7aNJU85KgnkrGKiEJMTnZJMSpbAvQdcUGm2q4s7Z2ZPA9iTwNd" \ "D92ESDXbxLt6WAsjaT5xHQNNgHBmwjgwscmPjE1dDuQ5rVC9Jowgu8q" assert derive_xkey(root, "m/1") == "xprv9v7aNJTyjf9pazc9j5X7CkK3t4ywxLzsWazZL9x8JE1f8f7dsv6" \ "xjtWEZN2cahUYqaEkr27oyGfc7Y8KG18B55j7h57W3SdiAvXcztzB7MV" assert derive_xkey(root, "m/44'/0'/0'", base58=True) == "xprv9zAN5JC2upM319x3bsP9aa1jbE9MoyXNuSkm9rTggLBgUSHwsvigCr" \ "wb3VJHpkb5KLteb9jwCpXnk7kS5ac3Av8Vn5UG2PgTdrxb9wPeipW" assert derive_xkey(root, "m/44'/0'/1'") == "xprv9zAN5JC2upM355bhe2xJWyzEVg7SD15PxVkN6FWPTjFPAkKoNoxPm" \ "xvC76SK6k7HDc1WQhYaXYyEUTTuVLYbKomAna5pFbDJCMVzfKHfZUS" pub = "xpub6D9iUoivkBuLHZgAk4VJt7vy3hwvcToFKifxtdv124nN3YewvMGeKmE" \ "fxLVZFLTCzQLS9NBwUzFVi66w5YnHM5o3y9GwQJSfroev539tkUZ" assert derive_xkey(pub, "m/0", hex=True) == decode_base58("xpub6FPUvcox6BxqQCt2GRHTdy5ehEKr3JRX1DjZTUutrRh8VsWNS6tfNZd5ZctuDZhm5d" \ "RdepkwBgz77p8dVmNuMbBifts556S6jy3gERc3Tfy", checksum= True).hex() assert derive_xkey(pub, "m/0", hex=False) == decode_base58("xpub6FPUvcox6BxqQCt2GRHTdy5ehEKr3JRX1DjZTUutrRh8VsWNS6tfNZd5ZctuDZhm5d" \ "RdepkwBgz77p8dVmNuMbBifts556S6jy3gERc3Tfy", checksum= True) assert derive_xkey(pub, "m/0/3/4") == "xpub6J7BeAMm9AYT56iBvZ8ceMksXimevjhcV9yCWM7UdkFZXWDvNHb7qLkFwwewtZp" \ "8bVKhsqZfHfvZN6KpT59BuQy4e93pP3AoXk8uzCu8aPJ" with pytest.raises(ValueError): derive_xkey("xprq9s21ZrQH143K39fFeGf2cWBTZ6NVj6ZsQ7nEK9f5pWqt4YwHPhnC" \ "F3GtMsPNA9cCz1j8j9Zs493ejkzJqUWqwGqQ2J8iNc1jFtFPbie7bZ4", "m/0'")
def test_xprivate_to_xpublic_key(): m = "debate pattern hotel silly grit must bronze athlete kitten salute salmon cat control hungry little" seed = mnemonic_to_seed(m) xPriv = create_master_xprivate_key(seed, hex=True) xp = "xpub661MyMwAqRbcFRtq6C9uK3bk7pmqc5ahhqDjxx6dfge6njx6jU9EhFwpLf" \ "iE6tQv8gjuez5PkQfxTZw4UUwwkut34JRYLWpJLNGPcUCGxj8" assert xp == xprivate_to_xpublic_key(xPriv) xPriv = create_master_xprivate_key(seed) assert xp == xprivate_to_xpublic_key(xPriv) xp = "xpub661iyMwAqRbcFRtq6C9uK3bk7pmqc5ahhqDjxx6dfge6njx6jU9EhFwpLf" \ "iE6tQv8gjuez5PkQfxTZw4UUwwkut34JRYLWpJLNGPcUCGxj8" with pytest.raises(ValueError): xprivate_to_xpublic_key(xp) with pytest.raises(TypeError): xprivate_to_xpublic_key(5656) p = "0488adez000000000000000000591dc86e17ddeda60b0bcbd4ada7ded84009c979d7a6c90e19106a51420b08d900a5" \ "595efba1a78dade67a53672ae52f2855e513b1bbc7381195e77ce6800da7f0" with pytest.raises(ValueError): xprivate_to_xpublic_key(p) xPriv = "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5Crq" \ "qTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47" assert "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXD" \ "SmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2" == xprivate_to_xpublic_key(xPriv) assert decode_base58("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXD" \ "SmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2", checksum=True).hex() == xprivate_to_xpublic_key(xPriv, hex=True) assert decode_base58("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXD" \ "SmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2", checksum=True) == xprivate_to_xpublic_key(xPriv, base58=False, hex=False)
def test_derive_child_xpublic_key(): xpub = "xpub661MyMwAqRbcFgWfEhiJneL1x2YcwTqMMvpx54rbY3oXsPvMLJnUZo8tsxpGFsUrFW" \ "9zMFKAGzaDDy1pR2uoohh1CW24Se1vkSnXRMqPV9R" assert "xpub68weA6at5vJ4Mzrpr7a6ZUvSkusBWEQLnFpgXMY1EWHNNpHgkSnX6HJwwSjN7z" \ "9PFrgTLK6gtWZ37o3b2ZAQSc4V9GdxdjVTjymSVit5Sai" == \ encode_base58(derive_child_xpublic_key(decode_base58(xpub, checksum=True), 0), checksum=True) assert "xpub68weA6at5vJ5fuUhS2bUgtse4cswz9VpU3UJAY93oUwpP8P4oDhTtGKizXsosJH99RWnnyD9txQ" \ "XBAcyAEiykRDAoyHLCcpW2vkrnsSymDQ" == \ encode_base58(derive_child_xpublic_key(decode_base58(xpub, checksum=True), 30), checksum=True) with pytest.raises(ValueError): derive_child_xpublic_key(decode_base58(xpub, checksum=True), 30 | 0x80000000)
def private_to_public_key(private_key, compressed=True, hex=True): """ Get public key from private key using ECDSA secp256k1 :param private_key: private key in WIF, HEX or bytes. :param compressed: (optional) flag of public key compressed format, by default set to True. In case private_key in WIF format, this flag is set in accordance with the key format specified in WIF string. :param hex: (optional) if set to True return key in HEX format, by default is True. :return: 33/65 bytes public key in HEX or bytes string. """ if not isinstance(private_key, bytes): if isinstance(private_key, bytearray): private_key = bytes(private_key) elif isinstance(private_key, str): try: if private_key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX, TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX): compressed = False h = decode_base58(private_key) if double_sha256(h[:-4])[:4] != h[-4:]: raise Exception() private_key = h[1:33] except: try: private_key = bytes_from_hex(private_key) except: raise ValueError("private key HEX or WIF invalid") else: raise ValueError("private key must be a bytes or WIF or hex encoded string") if len(private_key) != 32: raise ValueError("private key length invalid") pub = __secp256k1_ec_pubkey_create__(private_key, bool(compressed)) return pub.hex() if hex else pub
def test_is_xprivate_key_valid(): assert is_xprivate_key_valid( decode_base58( "xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQR" "eMWMdSpjE9qosHonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM", checksum=True)) == True assert is_xprivate_key_valid( "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBv" "feTg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47") == True assert is_xprivate_key_valid( "yprvAJXHiBz6oBHZouVo25rgayS7ss1FGAkAsPMrtpTX7DrAHqocTrus" "QmMNuA2VoJyxJ9jsfAQFRFoRrDFKAhNoVgvhLYSZ5LWqQJy7fYUzRW8") == True assert is_xprivate_key_valid( "uprv8tXDerPXZ1QsWSbPwQ6RR3S3YhsGBPzwCs2jTKmkMrk5VhWMvr6" "EGXLDE4oRTjX9pCMzERsgqZkd7bbgwuhCpKhVZEdDF6CUukNY3RLytkD") == True assert is_xprivate_key_valid( "zprvAc4DSBwiaXyw2RdtM1CDXgzUe4BMm6K33G91Dr8PHCx8LiJLW8jY" "tUpdfrjuDy9ega3Pyg3xiNiEZCL3hSw1JWRzKxnz7k9hsnsH8R1Ckwk") == True assert is_xprivate_key_valid( "vprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWF" "ntazMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe") == True assert is_xprivate_key_valid( "qprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWFn" "tazMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe") == False assert is_xprivate_key_valid("") == False assert is_xprivate_key_valid("1212qsdbfnn,i;p/") == False
def is_wif_valid(wif): """ Check is private key in WIF format string is valid. :param wif: private key in WIF format string. :return: boolean. """ if not isinstance(wif, str): raise TypeError("invalid wif key") if wif[0] not in PRIVATE_KEY_PREFIX_LIST: return False try: h = decode_base58(wif) except: return False checksum = h[-4:] if wif[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX, TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX): if len(h) != 37: return False elif len(h) != 38: return False if double_sha256(h[:-4])[:4] != checksum: return False return True
def is_xpublic_key_valid(key): """ Check the extended private key is valid according to BIP-0032. :param key: extended private key in BASE58, HEX or bytes string format. :return: boolean. """ if isinstance(key, str): try: key = decode_base58(key, verify_checksum=True) except: try: key = bytes.fromhex(key) except: pass if not isinstance(key, bytes) or len(key) != 78: return False if key[:4] not in [ MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX, MAINNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M49_XPUBLIC_KEY_PREFIX, MAINNET_M84_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX ]: return False return True
def test_create_master_xprivate_key(): e = "6afd4fd96ca02d0b7038429b77e8b32042fc205d031144054086130e8d83d981" xp = "xprv9s21ZrQH143K4LAkSUTJ3JiZ4cJc1FyRxCbPoWTQVssiezx3gpav8iJdHgg" \ "BTTUv37iQUrfNDYpGmTSP6zwFD2kJAFiUzpewivZUD6Jqdai" assert xp == create_master_xprivate_key( mnemonic_to_seed(entropy_to_mnemonic(e))) assert decode_base58(xp, checksum=True) == create_master_xprivate_key( mnemonic_to_seed(entropy_to_mnemonic(e)), base58=False)
def test_public_from_xpublic_key(): pub = "xpub6BP3EN8n7YTGYKL7nK9yUekCr9ixHK3taG2ATSkE5XjM7K12YMigC9pqUhj" \ "2K2f4TRg8xvDfqpHsWsjBHoMdJ6QF9dfSeKALRiTFAi9dA5T" assert public_from_xpublic_key(pub) == \ "02832b4cd1990dc9ffb7624bdc33e19061836f237f5ccd8730777a10bfca88944c" assert public_from_xpublic_key(decode_base58(pub, checksum=True))== \ "02832b4cd1990dc9ffb7624bdc33e19061836f237f5ccd8730777a10bfca88944c" assert public_from_xpublic_key(decode_base58(pub, checksum=True).hex())== \ "02832b4cd1990dc9ffb7624bdc33e19061836f237f5ccd8730777a10bfca88944c" with pytest.raises(TypeError): public_from_xpublic_key(423432) pub = "xpus6BP3EN8n7YTGYKL7nK9yUekCr9ixHK3taG2ATSkE5XjM7K12YMigC9pqUhj" \ "2K2f4TRg8xvDfqpHsWsjBHoMdJ6QF9dfSeKALRiTFAi9dA5T" with pytest.raises(ValueError): public_from_xpublic_key(pub)
def bip32_xkey_to_path_xkey(key, path_type, base58=True, hex=False): if path_type not in ("BIP44", "BIP49", "BIP84"): raise ValueError("unsupported path type %s" % path_type) if isinstance(key, str): try: key = decode_base58(key, verify_checksum=True) except: try: key = bytes.fromhex(key) except: pass if not isinstance(key, bytes) or len(key) != 78: raise ValueError("invalid key") if key[:4] == TESTNET_XPRIVATE_KEY_PREFIX: if path_type == "BIP44": key = TESTNET_M44_XPRIVATE_KEY_PREFIX + key[4:] elif path_type == "BIP49": key = TESTNET_M49_XPRIVATE_KEY_PREFIX + key[4:] else: key = TESTNET_M84_XPRIVATE_KEY_PREFIX + key[4:] elif key[:4] == MAINNET_XPRIVATE_KEY_PREFIX: if path_type == "BIP44": key = MAINNET_M44_XPRIVATE_KEY_PREFIX + key[4:] elif path_type == "BIP49": key = MAINNET_M49_XPRIVATE_KEY_PREFIX + key[4:] else: key = MAINNET_M84_XPRIVATE_KEY_PREFIX + key[4:] elif key[:4] == TESTNET_XPUBLIC_KEY_PREFIX: if path_type == "BIP44": key = TESTNET_M44_XPUBLIC_KEY_PREFIX + key[4:] elif path_type == "BIP49": key = TESTNET_M49_XPUBLIC_KEY_PREFIX + key[4:] else: key = TESTNET_M84_XPUBLIC_KEY_PREFIX + key[4:] elif key[:4] == MAINNET_XPUBLIC_KEY_PREFIX: if path_type == "BIP44": key = MAINNET_M44_XPUBLIC_KEY_PREFIX + key[4:] elif path_type == "BIP49": key = MAINNET_M49_XPUBLIC_KEY_PREFIX + key[4:] else: key = MAINNET_M84_XPUBLIC_KEY_PREFIX + key[4:] else: raise ValueError("invalid extended key") if hex: return key.hex() elif base58: return encode_base58(key, checksum=True) else: return key
def test_derive_child_xprivate_key(): xpriv = "xprv9s21ZrQH143K3CSC8gBJRWPHPzi8Y17VzhuMGgSyyiGYzbbCnmUE1zpR2iQCz" \ "VGPGAQBy2m7LTEtPAvfB6p2ECoQBAWtQYgYHpn1UFQv6Mi" assert "xprv9uxHkb3zFYjmC9AshDxocSv8SWphDkWq7VpNauF8hhGNMuqK2o4AKhhhuFADy1H5pVVAdZJCnyDmjZBZm" \ "gUR8aciXXELWfU6tCF4BCrhz5m" == \ encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 1), checksum=True) assert "xprv9uxHkb3zFYjm9WnMk636CLyiCt2h6mgVR2u5iy8PgAkPW1xYCuUGYUzU6A4HWS7hDhKVQufiymoj9oYjqg" \ "1h7331YjwVTfSBN97gSo65DiV" == \ encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 0), checksum=True) assert "xprv9uxHkb3zFYzv3TK97XAQ5YykGBuFgMo5mKzjvQKuzbPf3FBeVgTC2ozTtspLBU2X4HWWFDocpB1sHjSX" \ "Jby89m6cKhLhWUdhUWdF4o39kw4" == \ encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 20000), checksum=True) assert "xprv9uxHkb3zFzs4rMGo9d25NcHCyePGswYHY6fMk76DzbZ5iCucy7VtdjYa1o4n28bnnGLW4ComhMjNiUKx" \ "bgq6p6vc9zwHfHb1fvdhAvsURty" == \ encode_base58(derive_child_xprivate_key(decode_base58(xpriv, checksum=True), 2000000), checksum=True)
def test_decode_base58(): assert decode_base58("") == b"" assert decode_base58("1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1", True) == \ "00759d5f2b6d12712fef6f0f24c56804193e1aeac176c1faae" assert decode_base58("1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1", False).hex() == \ "00759d5f2b6d12712fef6f0f24c56804193e1aeac176c1faae" assert decode_base58("1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1", checksum=True).hex() == \ "00759d5f2b6d12712fef6f0f24c56804193e1aeac1" assert decode_base58("1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ1", verify_checksum=True).hex() == \ "00759d5f2b6d12712fef6f0f24c56804193e1aeac1" with pytest.raises(Exception): decode_base58("1Bitapsw1aT8hkLXFtXwZQfHgNwNJEyJJ2", verify_checksum=True) with pytest.raises(Exception): decode_base58(876)
def wif_to_private_key(h, hex=True): """ Decode WIF private key to bytes string or HEX encoded string :param hex: (optional) if set to True return key in HEX format, by default is True. :return: Private key HEX encoded string or raw bytes string. """ if not is_wif_valid(h): raise TypeError("invalid wif key") h = decode_base58(h) return h[1:33].hex() if hex else h[1:33]
def wif_to_private_key(h, hex=True): """ Decode WIF private key to bytes string or HEX encoded string :param hex: (optional) if set to True return key in HEX format, by default is True. :return: Private key HEX encoded string or raw bytes string. """ h = decode_base58(h) if double_sha256(h[:-4])[:4] != h[-4:]: raise TypeError("invalid wif key") return h[1:33].hex() if hex else h[1:33]
def test_private_from_xprivate_key(): priv = "xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qo" \ "sHonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM" assert private_from_xprivate_key(priv) == \ "L2BfXTBFwabUYoGkXKeR34f3TBpcThLtnC8yf6ZURvM952x8sWmz" assert private_from_xprivate_key(decode_base58(priv, checksum=True))== \ "L2BfXTBFwabUYoGkXKeR34f3TBpcThLtnC8yf6ZURvM952x8sWmz" assert private_from_xprivate_key(decode_base58(priv, checksum=True).hex(), hex=True)== \ wif_to_private_key("L2BfXTBFwabUYoGkXKeR34f3TBpcThLtnC8yf6ZURvM952x8sWmz", hex=True) assert private_from_xprivate_key(decode_base58(priv, checksum=True).hex(), wif=False)== \ wif_to_private_key("L2BfXTBFwabUYoGkXKeR34f3TBpcThLtnC8yf6ZURvM952x8sWmz", hex=False) with pytest.raises(TypeError): private_from_xprivate_key(423432) pub = "xpus6BP3EN8n7YTGYKL7nK9yUekCr9ixHK3taG2ATSkE5XjM7K12YMigC9pqUhj" \ "2K2f4TRg8xvDfqpHsWsjBHoMdJ6QF9dfSeKALRiTFAi9dA5T" with pytest.raises(ValueError): private_from_xprivate_key(pub) priv = "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5Crqq" \ "TpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47" assert private_from_xprivate_key(priv) == \ "cNu63US2f9jLLwDeD9321q1S5xviXCxSyem2GkFJjcF8DTWxqteC"
def xprivate_to_xpublic_key(xprivate_key, base58=True, hex=False): """ Get extended public key from extended private key using ECDSA secp256k1 :param str,bytes key: extended private key in base58, HEX or bytes string. :param boolean base58: (optional) return result as base58 encoded string, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True base58 flag value will be ignored. :return: extended public key in base58, HEX or bytes string format. """ if isinstance(xprivate_key, str): try: if len(xprivate_key) == 156: xprivate_key = bytes.fromhex(xprivate_key) else: xprivate_key = decode_base58(xprivate_key, checksum=True) except: raise ValueError("invalid extended private key") if not isinstance(xprivate_key, bytes): raise TypeError( "extended private key should be base58 string or bytes") if xprivate_key[:4] == TESTNET_XPRIVATE_KEY_PREFIX: prefix = TESTNET_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_XPRIVATE_KEY_PREFIX: prefix = MAINNET_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_M49_XPRIVATE_KEY_PREFIX: prefix = MAINNET_M49_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == TESTNET_M49_XPRIVATE_KEY_PREFIX: prefix = TESTNET_M49_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_M84_XPRIVATE_KEY_PREFIX: prefix = MAINNET_M84_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == TESTNET_M84_XPRIVATE_KEY_PREFIX: prefix = TESTNET_M84_XPUBLIC_KEY_PREFIX else: raise ValueError("invalid extended private key") key = b"".join([ prefix, xprivate_key[4:45], private_to_public_key(xprivate_key[46:], hex=False) ]) if hex: return key.hex() elif base58: key = b"".join([key, double_sha256(key)[:4]]) return encode_base58(key) else: return key
def address_to_hash(address, hex=True): """ Get address hash from base58 or bech32 address format. :param address: address in base58 or bech32 format. :param hex: (optional) If set to True return key in HEX format, by default is True. :return: script in HEX or bytes string. """ if address[0] in ADDRESS_PREFIX_LIST: h = decode_base58(address)[1:-4] elif address.split("1")[0] in (MAINNET_SEGWIT_ADDRESS_PREFIX, TESTNET_SEGWIT_ADDRESS_PREFIX): address = address.split("1")[1] h = rebase_5_to_8(rebase_32_to_5(address)[1:-6], False) else: return None return h.hex() if hex else h
def xkey_type(key): if isinstance(key, str): key = decode_base58(key, checksum=True) if len(key) != 78: raise Exception("invalid extended key") prefix = key[:4] if prefix in (MAINNET_XPRIVATE_KEY_PREFIX, MAINNET_M49_XPRIVATE_KEY_PREFIX, MAINNET_M84_XPRIVATE_KEY_PREFIX, TESTNET_XPRIVATE_KEY_PREFIX, TESTNET_M49_XPRIVATE_KEY_PREFIX, TESTNET_M84_XPRIVATE_KEY_PREFIX): return "private" if prefix in (MAINNET_XPUBLIC_KEY_PREFIX, MAINNET_M49_XPUBLIC_KEY_PREFIX, MAINNET_M84_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX, TESTNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX): return "public" raise ValueError("invalid extended key")
def xkey_network_type(key): if isinstance(key, str): key = decode_base58(key, checksum=True) if len(key) != 78: raise Exception("invalid extended key") prefix = key[:4] if prefix in (MAINNET_XPRIVATE_KEY_PREFIX, MAINNET_M49_XPRIVATE_KEY_PREFIX, MAINNET_M84_XPRIVATE_KEY_PREFIX, MAINNET_XPUBLIC_KEY_PREFIX, MAINNET_M49_XPUBLIC_KEY_PREFIX, MAINNET_M84_XPUBLIC_KEY_PREFIX): return "mainnet" if prefix in (TESTNET_XPRIVATE_KEY_PREFIX, TESTNET_M49_XPRIVATE_KEY_PREFIX, TESTNET_M84_XPRIVATE_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX, TESTNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX): return "testnet" raise Exception("invalid extended key")
def xkey_derivation_type(key): if isinstance(key, str): key = decode_base58(key, checksum=True) if len(key) != 78: return False prefix = key[:4] if prefix in (MAINNET_XPRIVATE_KEY_PREFIX, TESTNET_XPRIVATE_KEY_PREFIX, MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX): return "BIP44" if prefix in (MAINNET_M49_XPRIVATE_KEY_PREFIX, TESTNET_M49_XPRIVATE_KEY_PREFIX, MAINNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M49_XPUBLIC_KEY_PREFIX): return "BIP49" if prefix in (MAINNET_M84_XPRIVATE_KEY_PREFIX, TESTNET_M84_XPRIVATE_KEY_PREFIX, MAINNET_M84_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX): return "BIP84" return "custom"
def public_from_xpublic_key(xpublic_key, hex=True): """ Get public key from extended public key :param bytes xpublic_key: extended public in base58, HEX or bytes string format. :param boolean base58: (optional) return result as base58 encoded string, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True base58 flag value will be ignored. :return: public key in HEX or bytes string format. """ if isinstance(xpublic_key, str): if len(xpublic_key) == 156: xpublic_key = bytes.fromhex(xpublic_key) else: xpublic_key = decode_base58(xpublic_key, checksum=True) if not isinstance(xpublic_key, bytes): raise TypeError("xpublic_key should be HEX, Base58 or bytes string") if xpublic_key[:4] not in [ MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX ]: raise ValueError("invalid extended public key") return xpublic_key[45:].hex() if hex else xpublic_key[45:]
def path_xkey_to_bip32_xkey(key, base58=True, hex=False): if isinstance(key, str): try: key = decode_base58(key, verify_checksum=True) except: try: key = bytes.fromhex(key) except: pass if not isinstance(key, bytes) or len(key) != 78: raise ValueError("invalid extended key") if key[:4] in (MAINNET_XPUBLIC_KEY_PREFIX, TESTNET_XPUBLIC_KEY_PREFIX, MAINNET_XPRIVATE_KEY_PREFIX, TESTNET_XPRIVATE_KEY_PREFIX): pass elif key[:4] in (MAINNET_M49_XPUBLIC_KEY_PREFIX, MAINNET_M84_XPUBLIC_KEY_PREFIX): key = MAINNET_XPUBLIC_KEY_PREFIX + key[4:] elif key[:4] in (TESTNET_M49_XPUBLIC_KEY_PREFIX, TESTNET_M84_XPUBLIC_KEY_PREFIX): key = TESTNET_XPUBLIC_KEY_PREFIX + key[4:] elif key[:4] in (MAINNET_M49_XPRIVATE_KEY_PREFIX, MAINNET_M84_XPRIVATE_KEY_PREFIX): key = MAINNET_XPRIVATE_KEY_PREFIX + key[4:] elif key[:4] in (TESTNET_M49_XPRIVATE_KEY_PREFIX, TESTNET_M84_XPRIVATE_KEY_PREFIX): key = TESTNET_XPRIVATE_KEY_PREFIX + key[4:] else: raise ValueError("invalid extended key") if hex: return key.hex() elif base58: return encode_base58(key, checksum=True) else: return key
def derive_xkey(xkey, path, base58=None, hex=None, sub_path=False): """ Child Key derivation for extended private/public keys :param bytes xkey: extended private/public in base58, HEX or bytes string format. :param list path_level: list of derivation path levels. For hardened derivation use HARDENED_KEY flag. :param boolean base58: (optional) return result as base58 encoded string, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True base58 flag value will be ignored. :return: extended child private/public key in base58, HEX or bytes string format. """ if isinstance(path, str): path = decode_path(path, sub_path=sub_path) if isinstance(xkey, str): xkey = decode_base58(xkey, checksum=True) key_type = xkey_type(xkey) if key_type == 'private': for i in path: xkey = derive_child_xprivate_key(xkey, i) elif key_type == 'public': for i in path: xkey = derive_child_xpublic_key(xkey, i) else: raise ValueError("invalid extended key") if base58 is None and hex is None: base58 = True hex = False if hex: return xkey.hex() elif base58: return encode_base58(xkey, checksum=True) else: return xkey
def private_from_xprivate_key(xprivate_key, wif=True, hex=False): """ Get private key from extended private key :param bytes xprivate_key: extended public in base58, HEX or bytes string format. :param boolean wif: (optional) return result as WIF format, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True WIF flag value will be ignored. :return: private key in HEX or bytes string format. """ if isinstance(xprivate_key, str): if len(xprivate_key) == 156: xprivate_key = bytes.fromhex(xprivate_key) else: xprivate_key = decode_base58(xprivate_key, checksum=True) if not isinstance(xprivate_key, bytes): raise TypeError("xprivate_key should be HEX, Base58 or bytes string") prefix = xprivate_key[:4] if prefix in (MAINNET_XPRIVATE_KEY_PREFIX, MAINNET_M44_XPRIVATE_KEY_PREFIX, MAINNET_M49_XPRIVATE_KEY_PREFIX, MAINNET_M84_XPRIVATE_KEY_PREFIX): testnet = False elif prefix in (TESTNET_XPRIVATE_KEY_PREFIX, TESTNET_M44_XPRIVATE_KEY_PREFIX, TESTNET_M49_XPRIVATE_KEY_PREFIX, TESTNET_M84_XPRIVATE_KEY_PREFIX): testnet = True else: raise ValueError("invalid extended private key") if hex: return xprivate_key[46:].hex() elif wif: return private_key_to_wif(xprivate_key[46:], testnet=testnet) return xprivate_key[46:].hex() if hex else xprivate_key[46:]
def is_address_valid(address, testnet=False): """ Check is address valid. :param address: address in base58 or bech32 format. :param testnet: (optional) flag for testnet network, by default is False. :return: boolean. """ if not address or type(address) != str: return False if address[0] in (MAINNET_ADDRESS_PREFIX, MAINNET_SCRIPT_ADDRESS_PREFIX, TESTNET_ADDRESS_PREFIX, TESTNET_ADDRESS_PREFIX_2, TESTNET_SCRIPT_ADDRESS_PREFIX): if testnet: if address[0] not in (TESTNET_ADDRESS_PREFIX, TESTNET_ADDRESS_PREFIX_2, TESTNET_SCRIPT_ADDRESS_PREFIX): return False else: if address[0] not in (MAINNET_ADDRESS_PREFIX, MAINNET_SCRIPT_ADDRESS_PREFIX): return False h = decode_base58(address) if len(h) != 25: return False checksum = h[-4:] if double_sha256(h[:-4])[:4] != checksum: return False return True elif address[:2].lower() in (TESTNET_SEGWIT_ADDRESS_PREFIX, MAINNET_SEGWIT_ADDRESS_PREFIX): if len(address) not in (42, 62): return False try: prefix, payload = address.split('1') except: return False upp = True if prefix[0].isupper() else False for i in payload[1:]: if upp: if not i.isupper() or i not in base32charset_upcase: return False else: if i.isupper() or i not in base32charset: return False payload = payload.lower() prefix = prefix.lower() if testnet: if prefix != TESTNET_SEGWIT_ADDRESS_PREFIX: return False stripped_prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX else: if prefix != MAINNET_SEGWIT_ADDRESS_PREFIX: return False stripped_prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX d = rebase_32_to_5(payload) address_hash = d[:-6] checksum = d[-6:] checksum2 = bech32_polymod( b"%s%s%s" % (stripped_prefix, address_hash, b"\x00" * 6)) checksum2 = rebase_8_to_5(checksum2.to_bytes(5, "big"))[2:] if checksum != checksum2: return False return True
def test_path_xkey_to_bip32_xkey(): assert path_xkey_to_bip32_xkey(decode_base58("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcS" "kEQtKx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True)) == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkE" \ "QtKx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" assert path_xkey_to_bip32_xkey(decode_base58("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcS" "kEQtKx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True).hex()) == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkE" \ "QtKx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" with pytest.raises(ValueError): path_xkey_to_bip32_xkey("oeirfhoiwjefoiwe223") with pytest.raises(ValueError): path_xkey_to_bip32_xkey( decode_base58( "xpuw68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcS" "kEQtKx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True).hex()) assert path_xkey_to_bip32_xkey("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJa" "kFpxHwNyXDSmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2") == \ "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFp" \ "xHwNyXDSmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2" assert path_xkey_to_bip32_xkey("ypub6TZ8XHFAAptgVqYk8TMc2rqJrqVYYJwYnyinkpsLSJviSfRfztaS" "x1kihDCsndWJYY6xEqmLaHFraTwDok8knAgrG1ipNwuwtdakQibcvzB") == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQt" \ "Kx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" assert path_xkey_to_bip32_xkey("upub57Wa4MvRPNyAivfs3RdRnBNn6jhkarina5xLFiBMvCH4NVqWUPQU" "pKeh5KZfvYXDyYXStKeUzhrMcQt4p9upL1pW2EFdY8eMJjPA8UKuxaL") == \ "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakF" \ "pxHwNyXDSmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2" assert path_xkey_to_bip32_xkey("zpub6nPPpwv5KWSAM8jrxp9EEwvp2odzUvw3i6F1YDmDpKJbVmEuFYk1" "a5QriRATnYADxBDkzKMu2wcQTkYnXSYmaQNT8MRExrjSAMePoDv2d2R") == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQt" \ "Kx6ag1FHnirP8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" assert path_xkey_to_bip32_xkey("vpub5SLqN2bLY4WeaDrysnR3zGUHGhrCXUiHVCUZ375FJCewRbejj3a3" "SPJq6XXFvTB9PBeFdoF3TNCuVhVdXrKq8FW6tZx483TqaTSoWx3U88j") == \ "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakF" \ "pxHwNyXDSmSDzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2" assert path_xkey_to_bip32_xkey("xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQR" "eMWMdSpjE9qosHonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM") == \ "xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQR" \ "eMWMdSpjE9qosHonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM" assert path_xkey_to_bip32_xkey("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvf" "eTg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47") == \ "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfe" \ "Tg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47" assert path_xkey_to_bip32_xkey("yprvAJXHiBz6oBHZouVo25rgayS7ss1FGAkAsPMrtpTX7DrAHqocTrus" "QmMNuA2VoJyxJ9jsfAQFRFoRrDFKAhNoVgvhLYSZ5LWqQJy7fYUzRW8") == \ "xprv9yh2QXKBeVk5xcJgBj54NtLchtroKYkfxGqe7RZdjDUHEjzPDCkJ" \ "nhhEsx4uoQL2tWd4ugogxbSsxvdkSzxnhTF6UCk8VRhM8auUGwuyZMC" assert path_xkey_to_bip32_xkey("uprv8tXDerPXZ1QsWSbPwQ6RR3S3YhsGBPzwCs2jTKmkMrk5VhWMvr6E" "GXLDE4oRTjX9pCMzERsgqZkd7bbgwuhCpKhVZEdDF6CUukNY3RLytkD") == \ "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfe" \ "Tg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47" assert path_xkey_to_bip32_xkey("zprvAc4DSBwiaXyw2RdtM1CDXgzUe4BMm6K33G91Dr8PHCx8LiJLW8jY" "tUpdfrjuDy9ega3Pyg3xiNiEZCL3hSw1JWRzKxnz7k9hsnsH8R1Ckwk") == \ "xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQR" \ "eMWMdSpjE9qosHonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM" assert path_xkey_to_bip32_xkey("vprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWFnta" "zMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe", hex=True) == \ decode_base58("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfe" \ "Tg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", checksum=True).hex() assert path_xkey_to_bip32_xkey("vprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWFnta" "zMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe", base58=False) == \ decode_base58("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfe" \ "Tg5CrqqTpsEQZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", checksum=True)
def test_bip32_xkey_to_path_xkey(): assert bip32_xkey_to_path_xkey(decode_base58("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnir" "P8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True), "BIP44") == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnir" \ "P8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" assert bip32_xkey_to_path_xkey(decode_base58("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnir" "P8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", checksum=True).hex(), "BIP44") == \ "xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnir" \ "P8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X" assert bip32_xkey_to_path_xkey("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXDSmS" "DzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2", "BIP44") == \ "tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXDSmS" \ "DzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2" assert bip32_xkey_to_path_xkey("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnir" "P8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", "BIP49") == \ "ypub6TZ8XHFAAptgVqYk8TMc2rqJrqVYYJwYnyinkpsLSJviSfRfztaSx1kihDCsndW" \ "JYY6xEqmLaHFraTwDok8knAgrG1ipNwuwtdakQibcvzB" assert bip32_xkey_to_path_xkey("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXDSmS" "DzNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2", "BIP49") == \ "upub57Wa4MvRPNyAivfs3RdRnBNn6jhkarina5xLFiBMvCH4NVqWUPQUpKeh5KZfvYXD" \ "yYXStKeUzhrMcQt4p9upL1pW2EFdY8eMJjPA8UKuxaL" assert bip32_xkey_to_path_xkey("xpub68isDcaF29MCeYMdJ6ZypmjogsM6bgx3ssCZyRyT4JYqPZcSkEQtKx6ag1FHnirP" "8tz9VNAn7cuJhBKf63ijyw1FPg2Po36TcuX725Mom1X", "BIP84") == \ "zpub6nPPpwv5KWSAM8jrxp9EEwvp2odzUvw3i6F1YDmDpKJbVmEuFYk1a5QriRATnYAD" \ "xBDkzKMu2wcQTkYnXSYmaQNT8MRExrjSAMePoDv2d2R" assert bip32_xkey_to_path_xkey("tpubD6NzVbkrYhZ4YcS4zgyPcMzewmEkQ7CLs47HxSvAQ8AbH5wuJakFpxHwNyXDSmSD" "zNQmkKx2unk3xTDNN716cAKbgr6CyPm3hsAW4CqPVK2", "BIP84") == \ "vpub5SLqN2bLY4WeaDrysnR3zGUHGhrCXUiHVCUZ375FJCewRbejj3a3SPJq6XXFvTB9P" \ "BeFdoF3TNCuVhVdXrKq8FW6tZx483TqaTSoWx3U88j" assert bip32_xkey_to_path_xkey("xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qos" "HonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM", "BIP44") == \ "xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qos" \ "HonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM" assert bip32_xkey_to_path_xkey("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", "BIP44") == \ "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" \ "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47" assert bip32_xkey_to_path_xkey("xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qos" "HonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM", "BIP49") == \ "yprvAHDx8XGoRrSTB8SmWeQbKbtyU62upUKY89cnSTEVuCaFHcV7FUZzGRAVeenKE4VjG" \ "vvbECTQFiMgfuiUykWzWGkPTd6ZXqLDc4odjkNZA2Z" assert bip32_xkey_to_path_xkey("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", "BIP49") == \ "uprv8tXDerPXZ1QsWSbPwQ6RR3S3YhsGBPzwCs2jTKmkMrk5VhWMvr6EGXLDE4oRTjX9p" \ "CMzERsgqZkd7bbgwuhCpKhVZEdDF6CUukNY3RLytkD" assert bip32_xkey_to_path_xkey("xprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qos" "HonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM", "BIP84") == \ "zprvAc4DSBwiaXyw2RdtM1CDXgzUe4BMm6K33G91Dr8PHCx8LiJLW8jYtUpdfrjuDy9eg" \ "a3Pyg3xiNiEZCL3hSw1JWRzKxnz7k9hsnsH8R1Ckwk" assert bip32_xkey_to_path_xkey("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", "BIP84", hex=True) == \ decode_base58("vprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWF" "ntazMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe", checksum=True).hex() assert bip32_xkey_to_path_xkey("tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", "BIP84", base58=False) == \ decode_base58("vprv9DMUxX4ShgxMMjnWmkt3d8XYig1i81zS7yYxEifdjs7xYoKbBWF" "ntazMFGm1TeB5DqUnyuUFJE7AztDFfc7DcZP6RaKdq11yBUSBRvwZLXe", checksum=True) with pytest.raises(ValueError): bip32_xkey_to_path_xkey( "tprv8ZgxMBicQKsPf9QH73JoCxLYNjipEn1SHkWWfvsryrNCSbh8gBvfeTg5CrqqTpsEQ" "ZFBUxH8NuQ5EJz8EDHC261tgtvnfBNze2Jteoxhi47", "BIP88") with pytest.raises(ValueError): bip32_xkey_to_path_xkey("kjsdhfkjzxzvx][ewhf34h8322u32oeu2oh2", "BIP84") with pytest.raises(ValueError): bip32_xkey_to_path_xkey( decode_base58( "pprv9xPgprbtHAtyKqFegHcy7WoUJ7tTsrL3D36Zf4LcXCCNEWfszpQReMWMdSpjE9qos" "HonUirqo418nd6vG46yi34nbHQ8wvWjLLjzMBFKNqM", checksum=True), "BIP84")