Example #1
0
def test_fingerprint() -> None:

    seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad"
    xprv = rootxprv_from_seed(seed)
    pf = fingerprint(xprv)  # xprv is automatically converted to xpub
    child_key = derive(xprv, 0x80000000)
    pf2 = BIP32KeyData.deserialize(child_key).parent_fingerprint
    assert pf == pf2
Example #2
0
    def test_vector3(self):
        """BIP32 test vector 3

        https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
        """
        xkey_version = _PRV_VERSIONS[0]

        seed = "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"
        rootxprv = rootxprv_from_seed(seed, xkey_version)
        self.assertEqual(
            rootxprv,
            b"xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"
        )
        rootxpub = xpub_from_xprv(rootxprv)  # neutering
        self.assertEqual(
            rootxpub,
            b"xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"
        )

        xprv = rootxprv
        xpub = rootxpub

        xprv = derive(xprv, ".")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"
        )
        xprv = derive(rootxprv, "m")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6"
        )
        xpub = derive(xpub, ".")  # public relative
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"
        )
        xpub = derive(rootxpub, "m")  # public absolute
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"
        )

        xprv = derive(xprv, "./0'")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L"
        )
        xprv = derive(rootxprv, "m/0'")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"
        )
Example #3
0
def test_bips_pr905() -> None:
    "https://github.com/bitcoin/bips/pull/905"

    seed = "57fb1e450b8afb95c62afbcd49e4100d6790e0822b8905608679180ac34ca0bd45bf7ccc6c5f5218236d0eb93afc78bd117b9f02a6b7df258ea182dfaef5aad7"
    xroot = rootxprv_from_seed(seed)
    der_path = "m/44H/60H/0H"
    xprv = b"xprv9yqXG1Cns3YEQi6fsCJ7NGV5sHPiyZcbgLVst61dbLYyn7qy1G9aFtRmaYp481ounqnVf9Go2ymQ4gmxZLEwYSRhU868aDk4ZxzGvqHJVhe"
    assert derive(xroot, der_path) == xprv
    xpub = b"xpub6CpsfWjghR6XdCB8yDq7jQRpRKEDP2LT3ZRUgURF9g5xevB7YoTpogkFRqq5nQtVSN8YCMZo2CD8u4zCaxRv85ctCWmzEi9gQ5DBhBFaTNo"
    assert xpub_from_xprv(xprv) == xpub
Example #4
0
def test_bip39_vectors():
    """BIP32 test vectors from BIP39

    https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
    """
    filename = path.join(data_folder, "bip39_test_vectors.json")
    with open(filename, "r") as f:
        test_vectors = json.load(f)["english"]

    # test_vector[0] and [1], i.e. entropy and mnemonic, are tested in bip39
    for _, _, seed, key in test_vectors:
        assert rootxprv_from_seed(seed) == key.encode("ascii")
Example #5
0
def test_exceptions() -> None:

    with pytest.raises(ValueError, match="not a private or public key: "):
        # invalid checksum
        xprv = "xppp9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L"
        p2pkh(xprv)

    xpub = "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
    with pytest.raises(ValueError, match="not a private key: "):
        bip32.xpub_from_xprv(xpub)

    xpub_dict = bip32.deserialize(xpub)
    xpub_dict = bip32.deserialize(xpub_dict)
    xpub_dict["chain_code"] = (xpub_dict["chain_code"])[:-1]
    with pytest.raises(ValueError, match="invalid chain code length: "):
        xpub_dict = bip32.deserialize(xpub_dict)
    xpub_dict = bip32.deserialize(xpub)
    xpub_dict[
        "chain_code"] = "length is 32 but not a chaincode"  # type: ignore
    with pytest.raises(ValueError, match="invalid chain code"):
        xpub_dict = bip32.deserialize(xpub_dict)

    seed = "5b56c417303faa3fcba7e57400e120a0"
    with pytest.raises(ValueError, match="unknown private key version: "):
        version = b"\x04\x88\xAD\xE5"
        bip32.rootxprv_from_seed(seed, version)

    with pytest.raises(ValueError, match="too many bits for seed: "):
        bip32.rootxprv_from_seed(seed * 5)

    with pytest.raises(ValueError, match="too few bits for seed: "):
        bip32.rootxprv_from_seed(seed[:-2])
Example #6
0
    def test_p2pkh_from_wif(self):
        seed = b"00" * 32  # better be random
        rxprv = bip32.rootxprv_from_seed(seed)
        path = "m/0h/0h/12"
        xprv = bip32.derive(rxprv, path)
        wif = wif_from_xprv(xprv)
        self.assertEqual(
            wif, b'KyLk7s6Z1FtgYEVp3bPckPVnXvLUWNCcVL6wNt3gaT96EmzTKZwP')
        address = p2pkh_from_wif(wif)
        xpub = bip32.xpub_from_xprv(xprv)
        address2 = slip32.address_from_xpub(xpub)
        self.assertEqual(address, address2)

        self.assertRaises(ValueError, wif_from_xprv, xpub)
Example #7
0
def test_bip32_vectors():
    """BIP32 test vectors

    https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
    """
    filename = path.join(data_folder, "bip32_test_vectors.json")
    with open(filename, "r") as f:
        test_vectors = json.load(f)

    for seed in test_vectors:
        mxprv = rootxprv_from_seed(seed)
        for der_path, xpub, xprv in test_vectors[seed]:
            assert xprv == derive(mxprv, der_path).decode()
            assert xpub == xpub_from_xprv(xprv).decode()
Example #8
0
    def test_bip39_vectors(self):
        """BIP32 test vectors from BIP39

        https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
        """
        file = "bip39_test_vectors.json"
        filename = path.join(path.dirname(__file__), "data", file)
        with open(filename, 'r') as f:
            test_vectors = json.load(f)["english"]
        f.closed
        for test_vector in test_vectors:
            seed = test_vector[2]
            rootxprv = rootxprv_from_seed(seed)
            self.assertEqual(rootxprv, test_vector[3].encode('ascii'))
Example #9
0
    def test_bip32_vectors(self):
        """BIP32 test vector 3

        https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
        """
        fname = "bip32_test_vectors.json"
        filename = path.join(path.dirname(__file__), "test_data", fname)
        with open(filename, "r") as f:
            test_vectors = json.load(f)

        for seed in test_vectors:
            mxprv = rootxprv_from_seed(seed)
            for der_path, xpub, xprv in test_vectors[seed]:
                self.assertEqual(xprv, derive(mxprv, der_path).decode())
                self.assertEqual(xpub, xpub_from_xprv(xprv).decode())
Example #10
0
def test_p2pkh_from_wif() -> None:
    seed = b"00" * 32  # better be a documented test case
    rxprv = bip32.rootxprv_from_seed(seed)
    path = "m/0h/0h/12"
    xprv = bip32.derive(rxprv, path)
    wif = wif_from_prvkey(xprv)
    assert wif == b"KyLk7s6Z1FtgYEVp3bPckPVnXvLUWNCcVL6wNt3gaT96EmzTKZwP"
    pubkey, _ = pubkeyinfo_from_prvkey(wif)
    address = p2pkh(pubkey)
    xpub = bip32.xpub_from_xprv(xprv)
    address2 = slip132.address_from_xpub(xpub)
    assert address == address2

    err_msg = "not a private key: "
    with pytest.raises(ValueError, match=err_msg):
        wif_from_prvkey(xpub)
Example #11
0
def test_p2pkh_from_wif() -> None:
    seed = b"\x00" * 32  # better be a documented test case
    rxprv = bip32.rootxprv_from_seed(seed)
    path = "m/0h/0h/12"
    xprv = bip32.derive(rxprv, path)
    wif = wif_from_prvkey(xprv)
    assert wif == b"L2L1dqRmkmVtwStNf5wg8nnGaRn3buoQr721XShM4VwDbTcn9bpm"
    pubkey, _ = pubkeyinfo_from_prvkey(wif)
    address = p2pkh(pubkey)
    xpub = bip32.xpub_from_xprv(xprv)
    address2 = slip132.address_from_xpub(xpub)
    assert address == address2

    err_msg = "not a private key: "
    with pytest.raises(ValueError, match=err_msg):
        wif_from_prvkey(xpub)
Example #12
0
 def test_bip39_vectors(self):
     """BIP32 test vectors from BIP39
         https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
     """
     filename = "bip39_test_vectors.json"
     path_to_filename = os.path.join(os.path.dirname(__file__),
                                     "./data/",
                                     filename)
     with open(path_to_filename, 'r') as f:
         test_vectors = json.load(f)["english"]
     f.closed
     xkey_version = bip32.PRV_VERSION[0]
     for test_vector in test_vectors:
         seed = test_vector[2]
         rootxprv = bip32.rootxprv_from_seed(seed, xkey_version)
         self.assertEqual(rootxprv.decode(), test_vector[3])
Example #13
0
    def test_altnet(self):
        # non-bitcoin address version
        addr_version = 0x46.to_bytes(1, 'big')

        rootxprv = b'xprv9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L'

        # m/0'/0'/5'
        receive = b'VUqyLGVdUADWEqDqL2DeUBAcbPQwZfWDDY'
        indexes = [0x80000000, 0x80000000, 0x80000005]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, indexes)), addr_version)
        self.assertEqual(addr, receive)
        path = "m/0'/0'/5'"
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, path)), addr_version)
        self.assertEqual(addr, receive)

        # m/0'/1'/1'
        change = b'VMg6DpX7SQUsoECdpXJ8Bv6R7p11PfwHwy'
        indexes = [0x80000000, 0x80000001, 0x80000001]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, indexes)), addr_version)
        self.assertEqual(addr, change)
        path = "m/0'/1'/1'"
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, path)), addr_version)
        self.assertEqual(addr, change)

        xkey_version = bip32.PRV_VERSION[0]
        seed = "5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4c67196f57c39a88b76373733891bfaba16ed27a813ceed498804c0570"
        rootxprv = bip32.rootxprv_from_seed(seed, xkey_version)
        self.assertEqual(rootxprv, b'xprv9s21ZrQH143K3t4UZrNgeA3w861fwjYLaGwmPtQyPMmzshV2owVpfBSd2Q7YsHZ9j6i6ddYjb5PLtUdMZn8LhvuCVhGcQntq5rn7JVMqnie')

        indexes = [0x80000000, 0, 0]  # receive
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, indexes)), addr_version)
        self.assertEqual(addr, b'VTpEhLjvGYE16pLcNrMY53gQB9bbhn581W')

        indexes = [0x80000000, 1, 0]  # change
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(
            bip32.derive(rootxprv, indexes)), addr_version)
        self.assertEqual(addr, b'VRtaZvAe4s29aB3vuXyq7GYEpahsQet2B1')
Example #14
0
def test_derive_from_account() -> None:

    seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad"
    rmxprv = bip32.rootxprv_from_seed(seed)

    der_path = "m / 44 h / 0 h"
    mxpub = bip32.xpub_from_xprv(bip32.derive(rmxprv, der_path))

    test_vectors = [
        [0, 0],
        [0, 1],
        [0, 2],
        [1, 0],
        [1, 1],
        [1, 2],
    ]

    for branch, index in test_vectors:
        full_path = der_path + f"/{branch}/{index}"
        addr = p2pkh(bip32.derive(rmxprv, full_path)).decode()
        assert addr == p2pkh(bip32.derive_from_account(mxpub, branch,
                                                       index)).decode()

    errmsg = "invalid private derivation at branch level"
    with pytest.raises(ValueError, match=errmsg):
        bip32.derive_from_account(mxpub, 0x80000000, 0, True)

    errmsg = "invalid branch: "
    with pytest.raises(ValueError, match=errmsg):
        bip32.derive_from_account(mxpub, 2, 0)

    errmsg = "invalid private derivation at address index level"
    with pytest.raises(ValueError, match=errmsg):
        bip32.derive_from_account(mxpub, 0, 0x80000000)

    der_path = "m / 44 h / 0"
    mxpub = bip32.xpub_from_xprv(bip32.derive(rmxprv, der_path))
    errmsg = "public derivation at account level"
    with pytest.raises(UserWarning, match=errmsg):
        bip32.derive_from_account(mxpub, 0, 0)
Example #15
0
    def test_mainnet(self):
        # bitcoin core derivation style
        rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS"

        # m / 0h / 0h / 463h
        addr1 = b"1DyfBWxhVLmrJ7keyiHeMbt7N3UdeGU4G5"
        indexes = [0x80000000, 0x80000000, 0x800001CF]
        addr = p2pkh(xpub_from_xprv(derive(rootxprv, indexes)))
        self.assertEqual(addr, addr1)
        path = "m / 0h / 0h / 463h"
        addr = p2pkh(xpub_from_xprv(derive(rootxprv, path)))
        self.assertEqual(addr, addr1)

        # m / 0h / 0h / 267h
        addr2 = b"11x2mn59Qy43DjisZWQGRResjyQmgthki"
        indexes = [0x80000000, 0x80000000, 0x8000010B]
        addr = p2pkh(xpub_from_xprv(derive(rootxprv, indexes)))
        self.assertEqual(addr, addr2)
        path = "M / 0H / 0h // 267' / "
        addr = p2pkh(xpub_from_xprv(derive(rootxprv, path)))
        self.assertEqual(addr, addr2)

        seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad"
        xprv = rootxprv_from_seed(seed)
        xpub = "xpub661MyMwAqRbcFMYjmw8C6dJV97a4oLss6hb3v9wTQn2X48msQB61RCaLGtNhzgPCWPaJu7SvuB9EBSFCL43kTaFJC3owdaMka85uS154cEh"
        self.assertEqual(xpub_from_xprv(xprv).decode(), xpub)

        ind = "./0/0"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"1FcfDbWwGs1PmyhMVpCAhoTfMnmSuptH6g")

        ind = "./0/1"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"1K5GjYkZnPFvMDTGaQHTrVnd8wjmrtfR5x")

        ind = "./0/2"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"1PQYX2uN7NYFd7Hq22ECMzfDcKhtrHmkfi")

        ind = "./1/0"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"1BvSYpojWoWUeaMLnzbkK55v42DbizCoyq")

        ind = "./1/1"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"1NXB59hF4QzYpFrB7o6usLBjbk2D3ZqxAL")

        ind = "./1/2"
        addr = p2pkh(xpub_from_xprv(derive(xprv, ind)))
        self.assertEqual(addr, b"16NLYkKtvYhW1Jp86tbocku3gxWcvitY1w")

        # version/key mismatch in extended parent key
        temp = b58decode(rootxprv)
        bad_xprv = b58encode(temp[0:45] + b"\x01" + temp[46:], 78)
        self.assertRaises(ValueError, derive, bad_xprv, 1)
        # derive(bad_xprv, 1)

        # version/key mismatch in extended parent key
        xpub = xpub_from_xprv(rootxprv)
        temp = b58decode(xpub)
        bad_xpub = b58encode(temp[0:45] + b"\x00" + temp[46:], 78)
        self.assertRaises(ValueError, derive, bad_xpub, 1)
        # derive(bad_xpub, 1)

        # no private/hardened derivation from pubkey
        self.assertRaises(ValueError, derive, xpub, 0x80000000)
Example #16
0
    def test_mainnet_versions(self):

        # data cross-checked with Electrum and
        # https://jlopp.github.io/xpub-converter/

        # 128 bits
        raw_entr = bytes.fromhex("6" * 32)
        # 12 words
        mnemonic = bip39.mnemonic_from_entropy(raw_entr, "en")
        seed = bip39.seed_from_mnemonic(mnemonic, "")

        # p2pkh BIP44
        # m / 44h / coin_typeh / accounth / change / address_index
        path = "m/44h/0h/0h"
        version = NETWORKS["mainnet"]["bip32_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "xpub6C3uWu5Go5q62JzJpbjyCLYRGLYvexFeiepZTsYZ6SRexARkNfjG7GKtQVuGR3KHsyKsAwv7Hz3iNucPp6pfHiLvBczyK1j5CtBtpHB3NKx"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        address = p2pkh(xpub_ext)
        exp_address = b"1DDKKVHoFWGfctyEEJvrusqq6ipEaieGCq"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        address = p2pkh(xpub_int)
        exp_address = b"1FhKoffreKHzhtBMVW9NSsg3ZF148JPGoR"
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wsh-p2sh)
        # m / 49h / coin_typeh / accounth / change / address_index
        path = "m/49h/0h/0h"
        version = NETWORKS["mainnet"]["slip32_p2wsh_p2sh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "ypub6YBGdYufCVeoPVmNXfdrWhaBCXsQoLKNetNmD9bPTrKmnKVmiyU8f1uJqwGdmBb8kbAZpHoYfXQTLbWpkXc4skQDAreeCUXdbX9k8vtiHsN"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        address = p2wpkh_p2sh(xpub_ext)
        exp_address = b"3FmNAiTCWe5kPMgc4dtSgEdY8VuaCiJEH8"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        address = p2wpkh_p2sh(xpub_int)
        exp_address = b"34FLgkoRYX5Q5fqiZCZDwsK5GpXxmFuLJN"
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wpkh-p2sh)
        # m / 49h / coin_typeh / accounth / change / address_index
        path = "m/49h/0h/0h"
        version = NETWORKS["mainnet"]["slip32_p2wpkh_p2sh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "Ypub6j5Mkne6mTDAp4vkUL6qLmuyvKug1gzxyA2S8QrvqdABQW4gVNrQk8mEeeE7Kcp2z4EYgsofYjnxTm8b3km22EWt1Km3bszdVFRcipc6rXu"
        self.assertEqual(xpub.decode(), exp)

        # native segwit (p2wpkh)
        # m / 84h / coin_typeh / accounth / change / address_index
        path = "m/84h/0h/0h"
        version = NETWORKS["mainnet"]["slip32_p2wpkh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "zpub6qg3Uc1BAQkQvcBUYMmZHSzbsshSon3FvJ8yvH3ZZMjFNvJkwSji8UUwghiF3wvpvSvcNWVP8kfUhc2V2RwGp6pTC3ouj6njj956f26TniN"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        address = p2wpkh(xpub_ext)
        exp_address = b"bc1q0hy024867ednvuhy9en4dggflt5w9unw4ztl5a"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        address = p2wpkh(xpub_int)
        exp_address = b"bc1qy4x03jyl88h2zeg7l287xhv2xrwk4c3ztfpjd2"
        self.assertEqual(address, exp_address)

        # native segwit (p2wsh)
        # m / 84h / coin_typeh / accounth / change / address_index
        path = "m/84h/0h/0h"
        version = NETWORKS["mainnet"]["slip32_p2wsh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "Zpub72a8bqjcjNJnMBLrV2EY7XLQbfji28irEZneqYK6w8Zf16sfhr7zDbLsVQficP9j9uzbF6VW1y3ypmeFKf6Dxaw82WvK8WFjcsLyEvMNZjF"
        self.assertEqual(xpub.decode(), exp)
Example #17
0
    def test_testnet_versions(self):

        # data cross-checked with Electrum and
        # https://jlopp.github.io/xpub-converter/

        # 128 bits
        raw_entr = bytes.fromhex("6" * 32)
        # 12 words
        mnemonic = bip39.mnemonic_from_entropy(raw_entr, "en")
        seed = bip39.seed_from_mnemonic(mnemonic, "")

        # p2pkh BIP44
        # m / 44h / coin_typeh / accounth / change / address_index
        path = "m/44h/1h/0h"
        version = NETWORKS["testnet"]["bip32_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "tpubDChqWo2Xi2wNsxyJBE8ipcTJHLKWcqeeNUKBVTpUCNPZkHzHTm3qKAeHqgCou1t8PAY5ZnJ9QDa6zXSZxmjDnhiBpgZ7f6Yv88wEm5HXVbm"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        address = p2pkh(xpub_ext)
        exp_address = b"moutHSzeFWViMNEcvBxKzNCMj2kca8MvE1"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        address = p2pkh(xpub_int)
        exp_address = b"myWcXdNais9ExumnGKnNoJwoihQKfNPG9i"
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wsh-p2sh)
        # m / 49h / coin_typeh / accounth / change / address_index
        path = "m/49h/1h/0h"
        version = NETWORKS["testnet"]["slip32_p2wsh_p2sh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "upub5Dj8j7YrwodV68mt58QmNpSzjqjso2WMXEpLGLSvskKccGuXhCh3dTedkzVLAePA617UyXAg2vdswJXTYjU4qjMJaHU79GJVVJCAiy9ezZ2"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        address = p2wpkh_p2sh(xpub_ext)
        exp_address = b"2Mw8tQ6uT6mHhybarVhjgomUhHQJTeV9A2c"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        address = p2wpkh_p2sh(xpub_int)
        exp_address = b"2N872CRJ3E1CzWjfixXr3aeC3hkF5Cz4kWb"
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wsh-p2sh)
        # m / 49h / coin_typeh / accounth / change / address_index
        path = "m/49h/1h/0h"
        version = NETWORKS["testnet"]["slip32_p2wpkh_p2sh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "Upub5QdDrMHJWmBrWhwG1nskCtnoTdn91PBwqWU1BbiUFXA2ETUSTc5KiaWZZhSoj5c4KUBTr7Anv92P4U9Dqxd1zDTyQkaWYfmVP2U3Js1W5cG"
        self.assertEqual(xpub.decode(), exp)

        # native segwit (p2wpkh)
        # m / 84h / coin_typeh / accounth / change / address_index
        path = "m/84h/1h/0h"
        version = NETWORKS["testnet"]["slip32_p2wpkh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "vpub5ZhJmduYY7M5J2qCJgSW7hunX6zJrr5WuNg2kKt321HseZEYxqJc6Zso47aNXQw3Wf3sA8kppbfsxnLheUNXcL3xhzeBHLNp8fTVBN6DnJF"
        self.assertEqual(xpub.decode(), exp)
        # first addresses
        xpub_ext = derive(xpub, "./0/0")  # external
        # explicit network is required to discriminate from testnet
        address = p2wpkh(xpub_ext, "regtest")
        exp_address = b"bcrt1qv8lcnmj09rpdqwgl025h2deygur64z4hqf7me5"
        self.assertEqual(address, exp_address)
        xpub_int = derive(xpub, "./1/0")  # internal
        # explicit network is required to discriminate from testnet
        address = p2wpkh(xpub_int, "regtest")
        exp_address = b"bcrt1qqhxvky4y6qkwpvdzqjkdafmj20vs5trmt6y8w5"
        self.assertEqual(address, exp_address)

        # native segwit (p2wsh)
        # m / 84h / coin_typeh / accounth / change / address_index
        path = "m/84h/1h/0h"
        version = NETWORKS["testnet"]["slip32_p2wsh_prv"]
        rootprv = rootxprv_from_seed(seed, version)
        xprv = derive(rootprv, path)
        xpub = xpub_from_xprv(xprv)
        exp = "Vpub5kbPtsdz74uSibzaFLuUwnFbEu2a5Cm7DeKhfb9aPn8HGjoTjEgtBgjirpXr5r9wk87r2ikwhp4P5wxTwhXUkpAdYTkagjqp2PjMmGPBESU"
        self.assertEqual(xpub.decode(), exp)
Example #18
0
    def test_vector1(self):
        """BIP32 test vector 1

        https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
        """

        seed = "000102030405060708090a0b0c0d0e0f"
        rootxprv = rootxprv_from_seed(seed)
        self.assertEqual(
            rootxprv,
            b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
        )
        rootxpub = xpub_from_xprv(rootxprv)  # neutering
        self.assertEqual(
            rootxpub,
            b"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        )

        xprv = rootxprv
        xpub = rootxpub

        xprv = derive(xprv, ".")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
        )
        xprv = derive(rootxprv, "m")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
        )
        xpub = derive(xpub, ".")  # public relative
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        )
        xpub = derive(rootxpub, "m")  # public absolute
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
        )

        xprv = derive(xprv, "./0'")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"
        )
        xprv = derive(rootxprv, "m/0'")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
        )

        xprv = derive(xprv, "./1")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
        )
        xprv = derive(rootxprv, "m/0'/1")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
        )
        xpub = derive(xpub, "./1")  # public relative
        self.assertEqual(
            xpub,
            b"xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
        )

        xprv = derive(xprv, "./2H")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"
        )
        xprv = derive(rootxprv, "m/0'/1/2'")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
        )

        xprv = derive(xprv, "./2")  # private relative
        self.assertEqual(
            xprv,
            b"xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"
        )
        xprv = derive(rootxprv, "m/0'/1/2'/2")  # private absolute
        self.assertEqual(
            xprv,
            b"xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"
        )
        xpub = derive(xpub, "./2")  # public relative
        self.assertEqual(
            xpub,
            b"xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
        )

        xprv = derive(xprv, "./1000000000")  # private relative
        self.assertEqual(
            xprv,
            b"xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"
        )
        # private absolute
        xprv = derive(rootxprv, "m/0'/1/2'/2/1000000000")
        self.assertEqual(
            xprv,
            b"xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"
        )
        xpub = derive(xpub, "./1000000000")  # public relative
        self.assertEqual(
            xpub,
            b"xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
        )
Example #19
0
    def test_vector2(self):
        """BIP32 test vector 2

        https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
        """

        seed = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"
        rootxprv = rootxprv_from_seed(seed)
        self.assertEqual(
            rootxprv,
            b"xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"
        )
        rootxpub = xpub_from_xprv(rootxprv)  # neutering
        self.assertEqual(
            rootxpub,
            b"xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        )

        xprv = rootxprv
        xpub = rootxpub

        xprv = derive(xprv, ".")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"
        )
        xprv = derive(rootxprv, "m")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"
        )
        xpub = derive(xpub, ".")  # public relative
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        )
        xpub = derive(rootxpub, "m")  # public absolute
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
        )

        xprv = derive(xprv, "./0")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"
        )
        xprv = derive(rootxprv, "m/0")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"
        )
        xpub = derive(xpub, "./0")  # public relative
        self.assertEqual(
            xpub,
            b"xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
        )
        xpub = derive(rootxpub, "m/0")  # public absolute
        self.assertEqual(
            xpub,
            b"xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
        )

        xprv = derive(xprv, "./2147483647H")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"
        )
        xprv = derive(rootxprv, "m/0/2147483647H")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
        )

        xprv = derive(xprv, "./1")  # private relative
        self.assertEqual(
            xprv,
            b"xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"
        )
        xprv = derive(rootxprv, "m/0/2147483647H/1")  # private absolute
        self.assertEqual(
            xprv,
            b"xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"
        )
        xpub = derive(xpub, "./1")  # public relative
        self.assertEqual(
            xpub,
            b"xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
        )

        xprv = derive(xprv, "./2147483646H")  # private relative
        self.assertEqual(
            xprv,
            b"xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"
        )
        # private absolute
        xprv = derive(rootxprv, "m/0/2147483647H/1/2147483646H")
        self.assertEqual(
            xprv,
            b"xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
        )

        xprv = derive(xprv, "./2")  # private relative
        self.assertEqual(
            xprv,
            b"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
        )
        # private absolute
        xprv = derive(rootxprv, "m/0/2147483647H/1/2147483646H/2")
        self.assertEqual(
            xprv,
            b"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
        )
        xpub = derive(xpub, "./2")  # public relative
        self.assertEqual(
            xpub,
            b"xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
        )
        xpub = xpub_from_xprv(xprv)  # neutering
        self.assertEqual(
            xpub,
            b"xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
        )
Example #20
0
import secrets
from hashlib import sha256

from btclib import base58wif, bip32, bip39, btcmsg, der, slip32
from btclib.secpoint import bytes_from_point, point_from_octets
from btclib.utils import bytes_from_octets

mnemonic = "token output grass below such awake census safe orphan device other meat"
passphrase = ""
seed = bip39.seed_from_mnemonic(mnemonic, passphrase)
rxprv = bip32.rootxprv_from_seed(seed)
rxpub = bip32.xpub_from_xprv(rxprv)
assert rxpub == b"xpub661MyMwAqRbcFzL26X6G7bySxgU1oV6GviUrNnhbeAS3ULQq35KEV6uSf1aJXEHjFYy6LXUPrYnfR9bSKWdFZ5VnYaEb3AbHPmXFVAoKKYT", rxpub

firmware_xprv = bip32.derive(rxprv, "m/0")
firmware_xpub = bip32.derive(rxpub, "m/0")
assert firmware_xpub == bip32.xpub_from_xprv(bip32.derive(rxprv, "m/0"))
firmware_pubkey = bip32.deserialize(firmware_xpub)['key']
assert bytes_from_point(point_from_octets(firmware_pubkey), False).hex(
) == "042374b3b6b06b65a3b831f857634ea135bf10b014d5bba0f935cb9eb26a4b6547ed3b37f277427a0ab23bda0ca79c5785dc54d2387fa3f295f4d5674d5b637de2"
assert bytes_from_point(point_from_octets(firmware_pubkey), True).hex(
) == "022374b3b6b06b65a3b831f857634ea135bf10b014d5bba0f935cb9eb26a4b6547"
firmware_wif = base58wif.wif_from_xprv(firmware_xprv)
firmware_address = slip32.address_from_xpub(firmware_xpub)

app_xprv = bip32.derive(rxprv, "m/1")
app_xpub = bip32.derive(rxpub, "m/1")
assert app_xpub == bip32.xpub_from_xprv(bip32.derive(rxprv, "m/1"))
app_pubkey = bip32.deserialize(app_xpub)['key']
assert bytes_from_point(point_from_octets(app_pubkey), False).hex(
) == "04ae3d0d5c669ed364636e79e72abc012a33be63e537babddf56bfd393256acf6dba0fac21da6386513674573a2d7baff4375c9b6d2498383853c52f0565f97f1a"
Example #21
0
    def test_testnet_versions(self):

        # data cross-checked with Electrum and https://jlopp.github.io/xpub-converter/

        # 128 bits
        raw_entr = bytes.fromhex('6' * 32)
        # 12 words
        mnemonic = bip39.mnemonic_from_entropy(raw_entr, 'en')
        seed = bip39.seed_from_mnemonic(mnemonic, '')

        # p2pkh BIP44 m / 44' / coin_type' / account' / change / address_index
        path = "m/44h/1h/0h"
        version = bip32.TEST_tprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'tpubDChqWo2Xi2wNsxyJBE8ipcTJHLKWcqeeNUKBVTpUCNPZkHzHTm3qKAeHqgCou1t8PAY5ZnJ9QDa6zXSZxmjDnhiBpgZ7f6Yv88wEm5HXVbm'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'moutHSzeFWViMNEcvBxKzNCMj2kca8MvE1'
        self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'myWcXdNais9ExumnGKnNoJwoihQKfNPG9i'
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wpkh-p2sh) m / 49'/ coin_type' / account' / change / address_index
        path = "m/49h/1h/0h"
        version = bip32.TEST_uprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'upub5Dj8j7YrwodV68mt58QmNpSzjqjso2WMXEpLGLSvskKccGuXhCh3dTedkzVLAePA617UyXAg2vdswJXTYjU4qjMJaHU79GJVVJCAiy9ezZ2'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        address = bip32.p2wpkh_p2sh_address_from_xpub(xpub_ext)
        exp_address = b'2Mw8tQ6uT6mHhybarVhjgomUhHQJTeV9A2c'
        self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        address = bip32.p2wpkh_p2sh_address_from_xpub(xpub_int)
        exp_address = b'2N872CRJ3E1CzWjfixXr3aeC3hkF5Cz4kWb'
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wsh-p2sh) m / 49'/ coin_type' / account' / change / address_index
        path = "m/49h/1h/0h"
        version = bip32.TEST_Uprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Upub5QdDrMHJWmBrWhwG1nskCtnoTdn91PBwqWU1BbiUFXA2ETUSTc5KiaWZZhSoj5c4KUBTr7Anv92P4U9Dqxd1zDTyQkaWYfmVP2U3Js1W5cG'
        self.assertEqual(xpub, exp)

        # native segwit (p2wpkh) m / 84'/ coin_type' / account' / change / address_index
        path = "m/84h/1h/0h"
        version = bip32.TEST_vprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'vpub5ZhJmduYY7M5J2qCJgSW7hunX6zJrr5WuNg2kKt321HseZEYxqJc6Zso47aNXQw3Wf3sA8kppbfsxnLheUNXcL3xhzeBHLNp8fTVBN6DnJF'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        address = bip32.p2wpkh_address_from_xpub(xpub_ext)
        # this is regtest, not testnet!!
        exp_address = b'bcrt1qv8lcnmj09rpdqwgl025h2deygur64z4hqf7me5'
        # FIXME: self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        address = bip32.p2wpkh_address_from_xpub(xpub_int)
        # this is regtest, not testnet!!
        exp_address = b'bcrt1qqhxvky4y6qkwpvdzqjkdafmj20vs5trmt6y8w5'
        # FIXME: self.assertEqual(address, exp_address)

        # native segwit (p2wsh) m / 84'/ coin_type' / account' / change / address_index
        path = "m/84h/1h/0h"
        version = bip32.TEST_Vprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Vpub5kbPtsdz74uSibzaFLuUwnFbEu2a5Cm7DeKhfb9aPn8HGjoTjEgtBgjirpXr5r9wk87r2ikwhp4P5wxTwhXUkpAdYTkagjqp2PjMmGPBESU'
        self.assertEqual(xpub, exp)
Example #22
0
    def test_versions(self):

        # data cross-checked with Electrum and https://jlopp.github.io/xpub-converter/

        # 128 bits
        raw_entr = bytes.fromhex('6'*32)
        # 12 words
        mnemonic = bip39.mnemonic_from_entropy(raw_entr, 'en')
        seed = bip39.seed_from_mnemonic(mnemonic, '')

        ##### TESTNET

        # p2pkh BIP44 m / 44' / coin_type' / account' / change / address_index
        path = "m/44h/1h/0h"
        version = bip32.TEST_tprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'tpubDChqWo2Xi2wNsxyJBE8ipcTJHLKWcqeeNUKBVTpUCNPZkHzHTm3qKAeHqgCou1t8PAY5ZnJ9QDa6zXSZxmjDnhiBpgZ7f6Yv88wEm5HXVbm'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'moutHSzeFWViMNEcvBxKzNCMj2kca8MvE1'
        self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'myWcXdNais9ExumnGKnNoJwoihQKfNPG9i'
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wpkh-p2sh) m / 49'/ coin_type' / account' / change / address_index
        path = "m/49h/1h/0h"
        version = bip32.TEST_uprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'upub5Dj8j7YrwodV68mt58QmNpSzjqjso2WMXEpLGLSvskKccGuXhCh3dTedkzVLAePA617UyXAg2vdswJXTYjU4qjMJaHU79GJVVJCAiy9ezZ2'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        # TODO: address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'2Mw8tQ6uT6mHhybarVhjgomUhHQJTeV9A2c'
        # TODO: self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        # TODO: address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'2N872CRJ3E1CzWjfixXr3aeC3hkF5Cz4kWb'
        # TODO: self.assertEqual(address, exp_address)

        # multi-sig version
        version = bip32.TEST_Uprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Upub5QdDrMHJWmBrWhwG1nskCtnoTdn91PBwqWU1BbiUFXA2ETUSTc5KiaWZZhSoj5c4KUBTr7Anv92P4U9Dqxd1zDTyQkaWYfmVP2U3Js1W5cG'
        self.assertEqual(xpub, exp)

        # native segwit (p2wpkh) m / 84'/ coin_type' / account' / change / address_index
        path = "m/84h/1h/0h"
        version = bip32.TEST_vprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'vpub5ZhJmduYY7M5J2qCJgSW7hunX6zJrr5WuNg2kKt321HseZEYxqJc6Zso47aNXQw3Wf3sA8kppbfsxnLheUNXcL3xhzeBHLNp8fTVBN6DnJF'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'bcrt1qv8lcnmj09rpdqwgl025h2deygur64z4hqf7me5'
        # FIXME: self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'bcrt1qqhxvky4y6qkwpvdzqjkdafmj20vs5trmt6y8w5'
        # FIXME: self.assertEqual(address, exp_address)

        # multi-sig version
        version = bip32.TEST_Vprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Vpub5kbPtsdz74uSibzaFLuUwnFbEu2a5Cm7DeKhfb9aPn8HGjoTjEgtBgjirpXr5r9wk87r2ikwhp4P5wxTwhXUkpAdYTkagjqp2PjMmGPBESU'
        self.assertEqual(xpub, exp)

        ##### MAINNET

        # p2pkh BIP44 m / 44' / coin_type' / account' / change / address_index
        path = "m/44h/0h/0h"
        version = bip32.MAIN_xprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'xpub6C3uWu5Go5q62JzJpbjyCLYRGLYvexFeiepZTsYZ6SRexARkNfjG7GKtQVuGR3KHsyKsAwv7Hz3iNucPp6pfHiLvBczyK1j5CtBtpHB3NKx'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'1DDKKVHoFWGfctyEEJvrusqq6ipEaieGCq'
        self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'1FhKoffreKHzhtBMVW9NSsg3ZF148JPGoR'
        self.assertEqual(address, exp_address)

        # legacy segwit (p2wpkh-p2sh) m / 49'/ coin_type' / account' / change / address_index
        path = "m/49h/0h/0h"
        version = bip32.MAIN_yprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'ypub6YBGdYufCVeoPVmNXfdrWhaBCXsQoLKNetNmD9bPTrKmnKVmiyU8f1uJqwGdmBb8kbAZpHoYfXQTLbWpkXc4skQDAreeCUXdbX9k8vtiHsN'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'3FmNAiTCWe5kPMgc4dtSgEdY8VuaCiJEH8'
        # FIXME: self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'34FLgkoRYX5Q5fqiZCZDwsK5GpXxmFuLJN'
        # FIXME: self.assertEqual(address, exp_address)

        # multi-sig version
        version = bip32.MAIN_Yprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Ypub6j5Mkne6mTDAp4vkUL6qLmuyvKug1gzxyA2S8QrvqdABQW4gVNrQk8mEeeE7Kcp2z4EYgsofYjnxTm8b3km22EWt1Km3bszdVFRcipc6rXu'
        self.assertEqual(xpub, exp)

        # native segwit (p2wpkh) m / 84'/ coin_type' / account' / change / address_index
        path = "m/84h/0h/0h"
        version = bip32.MAIN_zprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'zpub6qg3Uc1BAQkQvcBUYMmZHSzbsshSon3FvJ8yvH3ZZMjFNvJkwSji8UUwghiF3wvpvSvcNWVP8kfUhc2V2RwGp6pTC3ouj6njj956f26TniN'
        self.assertEqual(xpub, exp)
        # first addresses
        xpub_ext = bip32.derive(xpub, "./0/0")  # external
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_ext)
        exp_address = b'bc1q0hy024867ednvuhy9en4dggflt5w9unw4ztl5a'
        # FIXME: self.assertEqual(address, exp_address)
        xpub_int = bip32.derive(xpub, "./1/0")  # internal
        # FIXME: address = bip32.p2pkh_address_from_xpub(xpub_int)
        exp_address = b'bc1qy4x03jyl88h2zeg7l287xhv2xrwk4c3ztfpjd2'
        # FIXME: self.assertEqual(address, exp_address)

        # multi-sig version
        version = bip32.MAIN_Zprv
        rootprv = bip32.rootxprv_from_seed(seed, version)
        xprv = bip32.derive(rootprv, path)
        xpub = bip32.xpub_from_xprv(xprv)
        exp = b'Zpub72a8bqjcjNJnMBLrV2EY7XLQbfji28irEZneqYK6w8Zf16sfhr7zDbLsVQficP9j9uzbF6VW1y3ypmeFKf6Dxaw82WvK8WFjcsLyEvMNZjF'
        self.assertEqual(xpub, exp)
Example #23
0
    def test_mainnet(self):
        # bitcoin core derivation style
        rootxprv = b'xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS'

        # m/0'/0'/463'
        addr1 = b'1DyfBWxhVLmrJ7keyiHeMbt7N3UdeGU4G5'
        indexes = [0x80000000, 0x80000000, 0x80000000 + 463]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(rootxprv, indexes)))
        self.assertEqual(addr, addr1)
        path = "m/0'/0'/463'"
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(rootxprv, path)))
        self.assertEqual(addr, addr1)

        # m/0'/0'/267'
        addr2 = b'11x2mn59Qy43DjisZWQGRResjyQmgthki'
        indexes = [0x80000000, 0x80000000, 0x80000000 + 267]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(rootxprv, indexes)))
        self.assertEqual(addr, addr2)
        path = "m/0'/0'/267'"
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(rootxprv, path)))
        self.assertEqual(addr, addr2)

        xkey_version = bip32.PRV_VERSION[0]
        seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad"
        seed = bytes.fromhex(seed)
        xprv = bip32.rootxprv_from_seed(seed, xkey_version)
        xpub = b'xpub661MyMwAqRbcFMYjmw8C6dJV97a4oLss6hb3v9wTQn2X48msQB61RCaLGtNhzgPCWPaJu7SvuB9EBSFCL43kTaFJC3owdaMka85uS154cEh'
        self.assertEqual(bip32.xpub_from_xprv(xprv), xpub)

        ind = [0, 0]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'1FcfDbWwGs1PmyhMVpCAhoTfMnmSuptH6g')

        ind = [0, 1]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'1K5GjYkZnPFvMDTGaQHTrVnd8wjmrtfR5x')

        ind = [0, 2]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'1PQYX2uN7NYFd7Hq22ECMzfDcKhtrHmkfi')

        ind = [1, 0]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'1BvSYpojWoWUeaMLnzbkK55v42DbizCoyq')

        ind = [1, 1]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'1NXB59hF4QzYpFrB7o6usLBjbk2D3ZqxAL')

        ind = [1, 2]
        addr = bip32.p2pkh_address_from_xpub(bip32.xpub_from_xprv(bip32.derive(xprv, ind)))
        self.assertEqual(addr, b'16NLYkKtvYhW1Jp86tbocku3gxWcvitY1w')

        # version/key mismatch in extended parent key
        temp = base58.decode_check(rootxprv)
        bad_xprv = base58.encode_check(temp[0:45] + b'\x01' + temp[46:])
        self.assertRaises(ValueError, bip32.ckd, bad_xprv, 1)
        #bip32.ckd(bad_xprv, 1)

        # version/key mismatch in extended parent key
        xpub = bip32.xpub_from_xprv(rootxprv)
        temp = base58.decode_check(xpub)
        bad_xpub = base58.encode_check(temp[0:45] + b'\x00' + temp[46:])
        self.assertRaises(ValueError, bip32.ckd, bad_xpub, 1)
        #bip32.ckd(bad_xpub, 1)

        # no private/hardened derivation from pubkey
        self.assertRaises(ValueError, bip32.ckd, xpub, 0x80000000)