Bitcoin Core 32.99.0
P2P Digital Currency
bip32_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2013-present 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>
12#include <util/bip32.h>
13#include <util/strencodings.h>
14
15#include <string>
16#include <vector>
17
18namespace {
19
20struct TestDerivation {
21 std::string pub;
22 std::string prv;
23 unsigned int nChild;
24};
25
26struct TestVector {
27 std::string strHexMaster;
28 std::vector<TestDerivation> vDerive;
29
30 explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}
31
32 TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
33 vDerive.emplace_back();
34 TestDerivation &der = vDerive.back();
35 der.pub = pub;
36 der.prv = prv;
37 der.nChild = nChild;
38 return *this;
39 }
40};
41
42TestVector test1 =
43 TestVector("000102030405060708090a0b0c0d0e0f")
44 ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
45 "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
47 ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
48 "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
49 1)
50 ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
51 "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
53 ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
54 "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
55 2)
56 ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
57 "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
58 1000000000)
59 ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
60 "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
61 0);
62
63TestVector test2 =
64 TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
65 ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
66 "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
67 0)
68 ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
69 "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
70 0xFFFFFFFF)
71 ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
72 "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
73 1)
74 ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
75 "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
76 0xFFFFFFFE)
77 ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
78 "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
79 2)
80 ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
81 "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
82 0);
83
84TestVector test3 =
85 TestVector("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be")
86 ("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
87 "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
89 ("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
90 "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
91 0);
92
93TestVector test4 =
94 TestVector("3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678")
95 ("xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa",
96 "xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv",
98 ("xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m",
99 "xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G",
101 ("xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt",
102 "xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1",
103 0);
104
105const std::vector<std::string> TEST5 = {
106 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm",
107 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH",
108 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn",
109 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ",
110 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4",
111 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J",
112 "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv",
113 "xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ",
114 "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN",
115 "xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8",
116 "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4",
117 "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9",
118 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx",
119 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G",
120 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY",
121 "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL"
122};
123
124void RunTest(const TestVector& test)
125{
126 std::vector<std::byte> seed{ParseHex<std::byte>(test.strHexMaster)};
127 CExtKey key;
128 CExtPubKey pubkey;
129 key.SetSeed(seed);
130 pubkey = key.Neuter();
131 for (const TestDerivation &derive : test.vDerive) {
132 // Test serialization round trip
133 DataStream ss{};
134 ss << key;
135 ss << pubkey;
136 BOOST_CHECK_EQUAL(ss.size(), 2 * BIP32_EXTKEY_SIZE);
137 CExtKey key_deser;
138 CExtPubKey pubkey_deser;
139 ss >> key_deser;
140 ss >> pubkey_deser;
141 BOOST_CHECK(key_deser == key);
142 BOOST_CHECK(pubkey_deser == pubkey);
143
144 // Test private key
145 BOOST_CHECK(EncodeExtKey(key) == derive.prv);
146 BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
147
148 // Test public key
149 BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
150 BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
151
152 // Derive new keys
153 CExtKey keyNew;
154 BOOST_CHECK(key.Derive(keyNew, derive.nChild));
155 CExtPubKey pubkeyNew = keyNew.Neuter();
156 if (!(derive.nChild & BIP32_HARDENED_FLAG)) {
157 // Compare with public derivation
158 CExtPubKey pubkeyNew2;
159 BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild));
160 BOOST_CHECK(pubkeyNew == pubkeyNew2);
161 }
162 key = keyNew;
163 pubkey = pubkeyNew;
164 }
165}
166
167} // namespace
168
170
172 RunTest(test1);
173}
174
176 RunTest(test2);
177}
178
180 RunTest(test3);
181}
182
184 RunTest(test4);
185}
186
188 for (const auto& str : TEST5) {
189 auto dec_extkey = DecodeExtKey(str);
190 auto dec_extpubkey = DecodeExtPubKey(str);
191 BOOST_CHECK_MESSAGE(!dec_extkey.key.IsValid(), "Decoding '" + str + "' as xprv should fail");
192 BOOST_CHECK_MESSAGE(!dec_extpubkey.pubkey.IsValid(), "Decoding '" + str + "' as xpub should fail");
193 }
194}
195
196BOOST_AUTO_TEST_CASE(bip32_deserialize_invalid)
197{
198 // A serialized extended key is exactly BIP32_EXTKEY_SIZE bytes. A shorter
199 // stream must throw rather than read past the end.
200 for (size_t len{0}; len < BIP32_EXTKEY_SIZE; ++len) {
201 CExtKey key;
202 CExtPubKey pubkey;
203 DataStream ss_key{std::vector<unsigned char>(len)};
204 DataStream ss_pubkey{std::vector<unsigned char>(len)};
205 BOOST_CHECK_THROW(ss_key >> key, std::ios_base::failure);
206 BOOST_CHECK_THROW(ss_pubkey >> pubkey, std::ios_base::failure);
207 }
208
209 // Serialize a valid depth-0 xprv/xpub to mutate below.
210 const CExtKey master{DecodeExtKey(test1.vDerive[0].prv)};
211 const CExtPubKey master_pub{master.Neuter()};
212 BOOST_REQUIRE(master.nDepth == 0);
213 std::vector<unsigned char> key_bytes, pubkey_bytes;
214 {
215 DataStream ss{};
216 ss << master;
217 const auto ss_span{MakeUCharSpan(ss)};
218 key_bytes.assign(ss_span.begin(), ss_span.end());
219 DataStream sp{};
220 sp << master_pub;
221 const auto sp_span{MakeUCharSpan(sp)};
222 pubkey_bytes.assign(sp_span.begin(), sp_span.end());
223 }
224 BOOST_CHECK_EQUAL(key_bytes.size(), BIP32_EXTKEY_SIZE);
225 BOOST_CHECK_EQUAL(pubkey_bytes.size(), BIP32_EXTKEY_SIZE);
226
227 // A longer stream is not invalid: exactly BIP32_EXTKEY_SIZE bytes are consumed
228 // and the trailing byte is left unread.
229 {
230 std::vector<unsigned char> extra{key_bytes};
231 extra.push_back(0);
232 DataStream ss{extra};
233 CExtKey key;
234 ss >> key;
235 BOOST_CHECK(key == master);
236 BOOST_CHECK_EQUAL(ss.size(), 1);
237 }
238 {
239 std::vector<unsigned char> extra{pubkey_bytes};
240 extra.push_back(0);
241 DataStream ss{extra};
242 CExtPubKey pubkey;
243 ss >> pubkey;
244 BOOST_CHECK(pubkey == master_pub);
245 BOOST_CHECK_EQUAL(ss.size(), 1);
246 }
247
248 const auto deser_extkey{[](std::vector<unsigned char> bytes) {
249 DataStream ss{bytes};
250 CExtKey key;
251 ss >> key;
252 return key;
253 }};
254 const auto deser_extpubkey{[](std::vector<unsigned char> bytes) {
255 DataStream ss{bytes};
256 CExtPubKey pubkey;
257 ss >> pubkey;
258 return pubkey;
259 }};
260
261 // Non-zero private key prefix (offset 41) => invalid.
262 {
263 auto bytes{key_bytes};
264 bytes[41] = 1;
265 BOOST_CHECK(!deser_extkey(bytes).key.IsValid());
266 }
267 // Non-zero child index with nDepth == 0 (offset 8) => invalid.
268 {
269 auto bytes{key_bytes};
270 bytes[8] = 1;
271 BOOST_CHECK(!deser_extkey(bytes).key.IsValid());
272 }
273 // Non-zero parent fingerprint with nDepth == 0 (offset 1) => invalid.
274 {
275 auto bytes{key_bytes};
276 bytes[1] = 1;
277 BOOST_CHECK(!deser_extkey(bytes).key.IsValid());
278 }
279 // Invalid public key header (offset 41) => invalid.
280 {
281 auto bytes{pubkey_bytes};
282 bytes[41] = 0;
283 BOOST_CHECK(!deser_extpubkey(bytes).pubkey.IsValid());
284 }
285 // Non-zero child index with nDepth == 0 (offset 8) => invalid.
286 {
287 auto bytes{pubkey_bytes};
288 bytes[8] = 1;
289 BOOST_CHECK(!deser_extpubkey(bytes).pubkey.IsValid());
290 }
291 // Non-zero parent fingerprint with nDepth == 0 (offset 1) => invalid.
292 {
293 auto bytes{pubkey_bytes};
294 bytes[1] = 1;
295 BOOST_CHECK(!deser_extpubkey(bytes).pubkey.IsValid());
296 }
297}
298
299BOOST_AUTO_TEST_CASE(bip32_derive_ext_key)
300{
301 const CExtKey master{DecodeExtKey(test1.vDerive[0].prv)};
302 const std::vector<uint32_t> path{test1.vDerive[0].nChild, test1.vDerive[1].nChild};
303 const auto derived{DeriveExtKey(master, path)};
304 BOOST_REQUIRE(derived);
305 BOOST_CHECK(EncodeExtKey(derived->first) == test1.vDerive[2].prv);
306
307 KeyOriginInfo expected_origin;
308 expected_origin.fingerprint = master.id_key_fingerprint();
309 expected_origin.path = path;
310 BOOST_CHECK(derived->second == expected_origin);
311
312 const auto root{DeriveExtKey(master, {})};
313 BOOST_REQUIRE(root);
314 BOOST_CHECK(root->first == master);
315 expected_origin.path.clear();
316 BOOST_CHECK(root->second == expected_origin);
317
318 CExtKey max_depth{master};
319 for (auto i{0}; i++ < 255;) {
320 CExtKey next_key;
321 BOOST_REQUIRE(max_depth.Derive(next_key, 0));
322 max_depth = next_key;
323 }
324 BOOST_CHECK(!DeriveExtKey(max_depth, {0}));
325}
326
327BOOST_AUTO_TEST_CASE(bip32_has_hardened_derivation)
328{
329 const std::vector<uint32_t> empty;
330 const std::vector<uint32_t> unhardened{0, 1, 2};
331 const std::vector<uint32_t> hardened{BIP32_HARDENED_FLAG};
332 const std::vector<uint32_t> mixed{0, BIP32_HARDENED_FLAG | 1, 2};
337}
338
339BOOST_AUTO_TEST_CASE(bip32_max_depth) {
340 CExtKey key_parent{DecodeExtKey(test1.vDerive[0].prv)}, key_child;
341 CExtPubKey pubkey_parent{DecodeExtPubKey(test1.vDerive[0].pub)}, pubkey_child;
342
343 // We can derive up to the 255th depth..
344 for (auto i = 0; i++ < 255;) {
345 BOOST_CHECK(key_parent.Derive(key_child, 0));
346 std::swap(key_parent, key_child);
347 BOOST_CHECK(pubkey_parent.Derive(pubkey_child, 0));
348 std::swap(pubkey_parent, pubkey_child);
349 }
350
351 // But trying to derive a non-existent 256th depth will fail!
352 BOOST_CHECK(key_parent.nDepth == 255);
353 BOOST_CHECK(pubkey_parent.nDepth == 255);
354 BOOST_CHECK(!key_parent.Derive(key_child, 0));
355 BOOST_CHECK(!pubkey_parent.Derive(pubkey_child, 0));
356}
357
358BOOST_AUTO_TEST_CASE(parse_hd_keypath)
359{
360 std::vector<uint32_t> keypath;
361
362 BOOST_CHECK(ParseHDKeypath("1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1", keypath));
363 BOOST_CHECK(!ParseHDKeypath("///////////////////////////", keypath));
364
365 BOOST_CHECK(ParseHDKeypath("1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1'/1", keypath));
366 BOOST_CHECK(!ParseHDKeypath("//////////////////////////'/", keypath));
367
368 BOOST_CHECK(ParseHDKeypath("1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/", keypath));
369 BOOST_CHECK(!ParseHDKeypath("1///////////////////////////", keypath));
370
371 BOOST_CHECK(ParseHDKeypath("1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1'/", keypath));
372 BOOST_CHECK(!ParseHDKeypath("1/'//////////////////////////", keypath));
373
374 BOOST_CHECK(ParseHDKeypath("", keypath));
375 BOOST_CHECK(!ParseHDKeypath(" ", keypath));
376
377 BOOST_CHECK(ParseHDKeypath("0", keypath));
378 BOOST_CHECK(!ParseHDKeypath("O", keypath));
379
380 BOOST_CHECK(ParseHDKeypath("0000'/0000'/0000'", keypath));
381 BOOST_CHECK(!ParseHDKeypath("0000,/0000,/0000,", keypath));
382
383 BOOST_CHECK(ParseHDKeypath("01234", keypath));
384 BOOST_CHECK(!ParseHDKeypath("0x1234", keypath));
385
386 BOOST_CHECK(ParseHDKeypath("1", keypath));
387 BOOST_CHECK(!ParseHDKeypath(" 1", keypath));
388
389 BOOST_CHECK(ParseHDKeypath("42", keypath));
390 BOOST_CHECK(!ParseHDKeypath("m42", keypath));
391
392 // A path element's numeric part is capped at 2^31-1; the top bit is
393 // reserved for the hardened marker (h or ').
394 BOOST_CHECK(ParseHDKeypath("2147483647", keypath)); // 0x7fffffff, largest normal index
395 BOOST_CHECK(!ParseHDKeypath("2147483648", keypath)); // 0x80000000, would set the hardened bit
396 BOOST_CHECK(!ParseHDKeypath("4294967295", keypath)); // 0xffffffff
397 BOOST_CHECK(!ParseHDKeypath("4294967296", keypath)); // uint32_t max + 1
398
399 BOOST_CHECK(ParseHDKeypath("m", keypath));
400 BOOST_CHECK(!ParseHDKeypath("n", keypath));
401
402 BOOST_CHECK(ParseHDKeypath("m/", keypath));
403 BOOST_CHECK(!ParseHDKeypath("n/", keypath));
404
405 BOOST_CHECK(ParseHDKeypath("m/0", keypath));
406 BOOST_CHECK(!ParseHDKeypath("n/0", keypath));
407
408 BOOST_CHECK(ParseHDKeypath("m/0'", keypath));
409 BOOST_CHECK(!ParseHDKeypath("m/0''", keypath));
410
411 BOOST_CHECK(ParseHDKeypath("m/0h", keypath));
412 BOOST_CHECK(!ParseHDKeypath("m/0hh", keypath));
413 BOOST_CHECK(!ParseHDKeypath("m/0x", keypath));
414 BOOST_CHECK(!ParseHDKeypath("m/0a", keypath));
415 BOOST_CHECK(!ParseHDKeypath("m/0G", keypath));
416 BOOST_CHECK(!ParseHDKeypath("m/h0", keypath));
417
418 keypath.clear();
419 BOOST_REQUIRE(ParseHDKeypath("m/0h/1h/2h", keypath));
420 BOOST_REQUIRE_EQUAL(keypath.size(), 3);
422 BOOST_CHECK_EQUAL(keypath[1], BIP32_HARDENED_FLAG | 1);
423 BOOST_CHECK_EQUAL(keypath[2], BIP32_HARDENED_FLAG | 2);
424
425 BOOST_CHECK(ParseHDKeypath("m/0'/0'", keypath));
426 BOOST_CHECK(ParseHDKeypath("m/0h/0h", keypath));
427 BOOST_CHECK(ParseHDKeypath("m/0'/0h", keypath));
428 BOOST_CHECK(!ParseHDKeypath("m/'0/0'", keypath));
429 BOOST_CHECK(!ParseHDKeypath("m/h0/0'", keypath));
430
431 BOOST_CHECK(ParseHDKeypath("m/0/0", keypath));
432 BOOST_CHECK(!ParseHDKeypath("n/0/0", keypath));
433
434 BOOST_CHECK(ParseHDKeypath("m/0/0/00", keypath));
435 BOOST_CHECK(!ParseHDKeypath("m/0/0/f00", keypath));
436
437 BOOST_CHECK(ParseHDKeypath("m/0/0/000000000000000000000000000000000000000000000000000000000000000000000000000000000000", keypath));
438 BOOST_CHECK(!ParseHDKeypath("m/1/1/111111111111111111111111111111111111111111111111111111111111111111111111111111111111", keypath));
439
440 BOOST_CHECK(ParseHDKeypath("m/0/00/0", keypath));
441 BOOST_CHECK(!ParseHDKeypath("m/0'/00/'0", keypath));
442
443 BOOST_CHECK(ParseHDKeypath("m/1/", keypath));
444 BOOST_CHECK(!ParseHDKeypath("m/1//", keypath));
445
446 // The cap applies to every element, wherever it sits in the path.
447 BOOST_CHECK(ParseHDKeypath("m/2147483647", keypath));
448 BOOST_CHECK(!ParseHDKeypath("m/2147483648", keypath));
449 BOOST_CHECK(!ParseHDKeypath("m/4294967295", keypath));
450 BOOST_CHECK(!ParseHDKeypath("m/4294967296", keypath));
451
452 BOOST_CHECK(ParseHDKeypath("m/0/2147483647", keypath));
453 BOOST_CHECK(!ParseHDKeypath("m/0/2147483648", keypath));
454 BOOST_CHECK(!ParseHDKeypath("m/0/4294967295", keypath));
455 BOOST_CHECK(!ParseHDKeypath("m/0/4294967296", keypath));
456}
457
bool ParseHDKeypath(const std::string &keypath_str, std::vector< uint32_t > &keypath)
Parse an HD keypaths like "m/7/0'/2000".
Definition: bip32.cpp:41
bool HasHardenedDerivation(std::span< const uint32_t > keypath)
Whether a parsed HD keypath contains at least one hardened derivation step.
Definition: bip32.cpp:77
static constexpr uint32_t BIP32_HARDENED_FLAG
BIP32 hardened derivation flag (2^31)
Definition: bip32.h:17
BOOST_AUTO_TEST_CASE(bip32_test1)
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:165
const std::string test1
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(headers.FindFirst("key"), "value")
std::optional< std::pair< CExtKey, KeyOriginInfo > > DeriveExtKey(const CExtKey &ext_key, const std::vector< uint32_t > &path)
Get extended key and origin info for a given path.
Definition: key.cpp:369
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:283
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:246
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:259
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:267
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:16
constexpr unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:22
constexpr auto MakeUCharSpan(const V &v) -> decltype(UCharSpanCast(std::span{v}))
Like the std::span constructor, but for (const) unsigned char member types only.
Definition: span.h:111
Basic testing setup.
Definition: setup_common.h:58
Definition: key.h:238
CExtPubKey Neuter() const
Definition: key.cpp:394
void SetSeed(std::span< const std::byte > seed)
Definition: key.cpp:381
KeyFingerprint fingerprint
First 32 bits of the Hash160 of the public key at the root of the path.
Definition: keyorigin.h:14
std::vector< uint32_t > path
Definition: keyorigin.h:15