LCOV - code coverage report
Current view: top level - src/test - bip32_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 128 128 100.0 %
Date: 2026-06-25 07:23:43 Functions: 66 66 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2013-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <boost/test/unit_test.hpp>
       6             : 
       7             : #include <clientversion.h>
       8             : #include <key.h>
       9             : #include <key_io.h>
      10             : #include <streams.h>
      11             : #include <test/util/setup_common.h>
      12             : #include <util/strencodings.h>
      13             : 
      14             : #include <string>
      15             : #include <vector>
      16             : 
      17             : namespace {
      18             : 
      19        2482 : struct TestDerivation {
      20             :     std::string pub;
      21             :     std::string prv;
      22             :     unsigned int nChild;
      23             : };
      24             : 
      25         584 : struct TestVector {
      26             :     std::string strHexMaster;
      27             :     std::vector<TestDerivation> vDerive;
      28             : 
      29        1168 :     explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}
      30             : 
      31        2482 :     TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
      32        2482 :         vDerive.emplace_back();
      33        2482 :         TestDerivation &der = vDerive.back();
      34        2482 :         der.pub = pub;
      35        2482 :         der.prv = prv;
      36        2482 :         der.nChild = nChild;
      37        2482 :         return *this;
      38             :     }
      39             : };
      40             : 
      41         146 : TestVector test1 =
      42        1022 :   TestVector("000102030405060708090a0b0c0d0e0f")
      43         146 :     ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
      44         146 :      "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
      45             :      0x80000000)
      46         146 :     ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
      47         146 :      "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
      48             :      1)
      49         146 :     ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
      50         146 :      "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
      51             :      0x80000002)
      52         146 :     ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
      53         146 :      "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
      54             :      2)
      55         146 :     ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
      56         146 :      "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
      57             :      1000000000)
      58         146 :     ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
      59         146 :      "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
      60             :      0);
      61             : 
      62         146 : TestVector test2 =
      63        1022 :   TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
      64         146 :     ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
      65         146 :      "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
      66             :      0)
      67         146 :     ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
      68         146 :      "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
      69             :      0xFFFFFFFF)
      70         146 :     ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
      71         146 :      "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
      72             :      1)
      73         146 :     ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
      74         146 :      "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
      75             :      0xFFFFFFFE)
      76         146 :     ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
      77         146 :      "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
      78             :      2)
      79         146 :     ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
      80         146 :      "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
      81             :      0);
      82             : 
      83         146 : TestVector test3 =
      84         438 :   TestVector("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be")
      85         146 :     ("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
      86         146 :      "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
      87             :       0x80000000)
      88         146 :     ("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
      89         146 :      "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
      90             :       0);
      91             : 
      92         146 : TestVector test4 =
      93         584 :   TestVector("3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678")
      94         146 :     ("xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa",
      95         146 :      "xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv",
      96             :      0x80000000)
      97         146 :     ("xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m",
      98         146 :      "xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G",
      99             :      0x80000001)
     100         146 :     ("xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt",
     101         146 :      "xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1",
     102             :      0);
     103             : 
     104         146 : const std::vector<std::string> TEST5 = {
     105         146 :     "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm",
     106         146 :     "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH",
     107         146 :     "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn",
     108         146 :     "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ",
     109         146 :     "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4",
     110         146 :     "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J",
     111         146 :     "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv",
     112         146 :     "xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ",
     113         146 :     "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN",
     114         146 :     "xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8",
     115         146 :     "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4",
     116         146 :     "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9",
     117         146 :     "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx",
     118         146 :     "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G",
     119         146 :     "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY",
     120         146 :     "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL"
     121             : };
     122             : 
     123           4 : void RunTest(const TestVector& test)
     124             : {
     125           4 :     std::vector<std::byte> seed{ParseHex<std::byte>(test.strHexMaster)};
     126           4 :     CExtKey key;
     127           4 :     CExtPubKey pubkey;
     128           4 :     key.SetSeed(MakeByteSpan(seed));
     129           4 :     pubkey = key.Neuter();
     130          21 :     for (const TestDerivation &derive : test.vDerive) {
     131             :         unsigned char data[74];
     132          17 :         key.Encode(data);
     133          17 :         pubkey.Encode(data);
     134             : 
     135             :         // Test private key
     136          17 :         BOOST_CHECK(EncodeExtKey(key) == derive.prv);
     137          17 :         BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
     138             : 
     139             :         // Test public key
     140          17 :         BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
     141          17 :         BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
     142             : 
     143             :         // Derive new keys
     144          17 :         CExtKey keyNew;
     145          17 :         BOOST_CHECK(key.Derive(keyNew, derive.nChild));
     146          17 :         CExtPubKey pubkeyNew = keyNew.Neuter();
     147          17 :         if (!(derive.nChild & 0x80000000)) {
     148             :             // Compare with public derivation
     149          10 :             CExtPubKey pubkeyNew2;
     150          10 :             BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild));
     151          10 :             BOOST_CHECK(pubkeyNew == pubkeyNew2);
     152          10 :         }
     153          17 :         key = keyNew;
     154          17 :         pubkey = pubkeyNew;
     155          17 :     }
     156           4 : }
     157             : 
     158             : }  // namespace
     159             : 
     160         146 : BOOST_FIXTURE_TEST_SUITE(bip32_tests, BasicTestingSetup)
     161             : 
     162         149 : BOOST_AUTO_TEST_CASE(bip32_test1) {
     163           1 :     RunTest(test1);
     164           1 : }
     165             : 
     166         149 : BOOST_AUTO_TEST_CASE(bip32_test2) {
     167           1 :     RunTest(test2);
     168           1 : }
     169             : 
     170         149 : BOOST_AUTO_TEST_CASE(bip32_test3) {
     171           1 :     RunTest(test3);
     172           1 : }
     173             : 
     174         149 : BOOST_AUTO_TEST_CASE(bip32_test4) {
     175           1 :     RunTest(test4);
     176           1 : }
     177             : 
     178         149 : BOOST_AUTO_TEST_CASE(bip32_test5) {
     179          17 :     for (const auto& str : TEST5) {
     180          16 :         auto dec_extkey = DecodeExtKey(str);
     181          16 :         auto dec_extpubkey = DecodeExtPubKey(str);
     182          16 :         BOOST_CHECK_MESSAGE(!dec_extkey.key.IsValid(), "Decoding '" + str + "' as xprv should fail");
     183          16 :         BOOST_CHECK_MESSAGE(!dec_extpubkey.pubkey.IsValid(), "Decoding '" + str + "' as xpub should fail");
     184          16 :     }
     185           1 : }
     186             : 
     187         149 : BOOST_AUTO_TEST_CASE(bip32_max_depth) {
     188           1 :     CExtKey key_parent{DecodeExtKey(test1.vDerive[0].prv)}, key_child;
     189           1 :     CExtPubKey pubkey_parent{DecodeExtPubKey(test1.vDerive[0].pub)}, pubkey_child;
     190             : 
     191             :     // We can derive up to the 255th depth..
     192         256 :     for (auto i = 0; i++ < 255;) {
     193         255 :         BOOST_CHECK(key_parent.Derive(key_child, 0));
     194         255 :         std::swap(key_parent, key_child);
     195         255 :         BOOST_CHECK(pubkey_parent.Derive(pubkey_child, 0));
     196         255 :         std::swap(pubkey_parent, pubkey_child);
     197             :     }
     198             : 
     199             :     // But trying to derive a non-existent 256th depth will fail!
     200           1 :     BOOST_CHECK(key_parent.nDepth == 255 && pubkey_parent.nDepth == 255);
     201           1 :     BOOST_CHECK(!key_parent.Derive(key_child, 0));
     202           1 :     BOOST_CHECK(!pubkey_parent.Derive(pubkey_child, 0));
     203           1 : }
     204             : 
     205         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16