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()