Branch data Line data Source code
1 : : // Copyright (c) 2019-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 <util/bip32.h>
6 : :
7 : : #include <tinyformat.h>
8 : : #include <util/strencodings.h>
9 : :
10 : : #include <algorithm>
11 : : #include <cstdint>
12 : : #include <cstdio>
13 : : #include <optional>
14 : : #include <span>
15 : : #include <sstream>
16 : :
17 : 327 : bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
18 : : {
19 : 327 : std::stringstream ss(keypath_str);
20 : 327 : std::string item;
21 : 327 : bool first = true;
22 [ + - + + : 150382 : while (std::getline(ss, item, '/') || std::getline(ss, item, 'h')) {
+ - - + ]
23 [ + + ]: 150143 : if (item.compare("m") == 0) {
24 [ + + ]: 223 : if (first) {
25 : 221 : first = false;
26 : 221 : continue;
27 : : }
28 : : return false;
29 : : }
30 : : // Finds whether it is hardened
31 : 149920 : uint32_t path = 0;
32 : 149920 : size_t pos = item.find('\'');
33 [ + + ]: 149920 : if (pos == std::string::npos) {
34 : 145990 : pos = item.find('h');
35 : : }
36 [ + + ]: 145990 : if (pos != std::string::npos) {
37 : : // The hardened tick can only be in the last index of the string
38 [ - + + + ]: 4052 : if (pos != item.size() - 1) {
39 : : return false;
40 : : }
41 : 4043 : path |= 0x80000000;
42 [ + - ]: 4043 : item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
43 : : }
44 : :
45 : : // Ensure this is only numbers
46 [ - + ]: 149911 : const auto number{ToIntegral<uint32_t>(item)};
47 [ + + ]: 149911 : if (!number) {
48 : : return false;
49 : : }
50 : : // A BIP32 child index is 31 bits; the top bit is reserved for the
51 : : // hardened marker, so the numeric part must not exceed 2^31 - 1.
52 [ + - ]: 149834 : if (*number > 0x7fffffff) {
53 : : return false;
54 : : }
55 [ + - ]: 149834 : path |= *number;
56 : :
57 [ + - ]: 149834 : keypath.push_back(path);
58 : : first = false;
59 : : }
60 : : return true;
61 : 327 : }
62 : :
63 : 5683974 : std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe)
64 : : {
65 : 5683974 : std::string ret;
66 [ + + ]: 11123195 : for (auto i : path) {
67 [ + - ]: 10878442 : ret += strprintf("/%i", (i << 1) >> 1);
68 [ + + + + ]: 7836126 : if (i >> 31) ret += apostrophe ? '\'' : 'h';
69 : : }
70 : 5683974 : return ret;
71 : 0 : }
72 : :
73 : 218 : std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe)
74 : : {
75 [ + - ]: 436 : return "m" + FormatHDKeypath(keypath, apostrophe);
76 : : }
77 : :
78 : 1814573 : bool HasHardenedDerivation(std::span<const uint32_t> keypath)
79 : : {
80 : 1814573 : return std::any_of(keypath.begin(), keypath.end(), [](uint32_t index) {
81 [ + + ]: 1736162 : return index >> 31;
82 : 1814573 : });
83 : : }
|