0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-10 10:52:31 -05:00
bitcoin-bitcoin-core/src/util/bip32.cpp
Andrew Chow fa53611cf1
Merge bitcoin/bitcoin#26076: Switch hardened derivation marker to h
fe49f06c0e doc: clarify PR 26076 release note (Sjors Provoost)
bd13dc2f46 Switch hardened derivation marker to h in descriptors (Sjors Provoost)

Pull request description:

  This makes it easier to handle descriptor strings manually, especially when importing from another Bitcoin Core wallet.

  For example the `importdescriptors` RPC call is easiest to use `h` as the marker: `'["desc": ".../0h/..."]'`, avoiding the need for escape characters. With this change `listdescriptors` will use `h`, so you can copy-paste the result, without having to add escape characters or switch `'` to 'h' manually.

  Both markers can still be parsed.

  The `hdkeypath` field in `getaddressinfo` is also impacted by this change, except for legacy wallets. The latter is to prevent accidentally breaking ancient software that uses our legacy wallet.

  See discussion in #15740

ACKs for top commit:
  achow101:
    ACK fe49f06c0e
  darosior:
    re-ACK fe49f06c0e

Tree-SHA512: f78bc873b24a6f7a2bf38f5dd58f2b723e35e6b10e4d65c36ec300e2d362d475eeca6e5afa04b3037ab4bee0bf8ebc93ea5fc18102a2111d3d88fc873c08dc89
2023-05-08 13:31:28 -04:00

67 lines
1.9 KiB
C++

// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <tinyformat.h>
#include <util/bip32.h>
#include <util/strencodings.h>
#include <cstdint>
#include <cstdio>
#include <sstream>
bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
{
std::stringstream ss(keypath_str);
std::string item;
bool first = true;
while (std::getline(ss, item, '/')) {
if (item.compare("m") == 0) {
if (first) {
first = false;
continue;
}
return false;
}
// Finds whether it is hardened
uint32_t path = 0;
size_t pos = item.find('\'');
if (pos != std::string::npos) {
// The hardened tick can only be in the last index of the string
if (pos != item.size() - 1) {
return false;
}
path |= 0x80000000;
item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
}
// Ensure this is only numbers
if (item.find_first_not_of( "0123456789" ) != std::string::npos) {
return false;
}
uint32_t number;
if (!ParseUInt32(item, &number)) {
return false;
}
path |= number;
keypath.push_back(path);
first = false;
}
return true;
}
std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe)
{
std::string ret;
for (auto i : path) {
ret += strprintf("/%i", (i << 1) >> 1);
if (i >> 31) ret += apostrophe ? '\'' : 'h';
}
return ret;
}
std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe)
{
return "m" + FormatHDKeypath(keypath, apostrophe);
}