Merge bitcoin/bitcoin#32745: scripted-diff: Update DeriveType enum values to mention ranged derivations

a099655f2e scripted-diff: Update `DeriveType` enum values to mention ranged derivations (rkrux)

Pull request description:

  While reviewing the MuSig2 descriptors PR #31244, I realized that the enum
  `DeriveType` here logically refers to the derive type for ranged descriptors.
  This became evident to me while going through the implementations of `IsRange`
   & `IsHardened` functions of `BIP32PubkeyProvider`, and the `ParsePubkeyInner`
  function. Initially I got confused by reading `IsRange` translating to
  `!= DeriveType::NO`, but later realised it specifically referred to the presence
   of ranged derivations. I propose explicitly mentioning "ranged" in the values
  of the `DeriveType` enum would make it easier to parse the descriptors code.

  This enum is used in one file only - `script/descriptors.cpp`. That's why I
  explicitly passed it as the argument in the `sed` command in the script.

ACKs for top commit:
  hodlinator:
    re-ACK a099655f2e
  pablomartin4btc:
    ACK a099655f2e
  PeterWrighten:
    ACK a099655

Tree-SHA512: 03f11e5a37edd4f92b7113c13cdeabb11c62cc5d836874f9a4eee107362d64a1745e6a65079033dc260a58d8693bccc9dce9c18e9433a05258e8a6b34242514c
This commit is contained in:
merge-script committed 2026-02-19 13:27:29 +01:00
commit 5a8a427610
1 file changed
+27 -27
+27 -27
View File
@@ -366,9 +366,9 @@ public:
}; };
enum class DeriveType { enum class DeriveType {
NO, NON_RANGED,
UNHARDENED, UNHARDENED_RANGED,
HARDENED, HARDENED_RANGED,
}; };
/** An object representing a parsed extended public key in a descriptor. */ /** An object representing a parsed extended public key in a descriptor. */
@@ -408,7 +408,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
bool IsHardened() const bool IsHardened() const
{ {
if (m_derive == DeriveType::HARDENED) return true; if (m_derive == DeriveType::HARDENED_RANGED) return true;
for (auto entry : m_path) { for (auto entry : m_path) {
if (entry >> 31) return true; if (entry >> 31) return true;
} }
@@ -417,7 +417,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
public: public:
BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive, bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {} BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive, bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {}
bool IsRange() const override { return m_derive != DeriveType::NO; } bool IsRange() const override { return m_derive != DeriveType::NON_RANGED; }
size_t GetSize() const override { return 33; } size_t GetSize() const override { return 33; }
bool IsBIP32() const override { return true; } bool IsBIP32() const override { return true; }
std::optional<CPubKey> GetPubKey(int pos, const SigningProvider& arg, FlatSigningProvider& out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override std::optional<CPubKey> GetPubKey(int pos, const SigningProvider& arg, FlatSigningProvider& out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
@@ -426,8 +426,8 @@ public:
CKeyID keyid = m_root_extkey.pubkey.GetID(); CKeyID keyid = m_root_extkey.pubkey.GetID();
std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint); std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
info.path = m_path; info.path = m_path;
if (m_derive == DeriveType::UNHARDENED) info.path.push_back((uint32_t)pos); if (m_derive == DeriveType::UNHARDENED_RANGED) info.path.push_back((uint32_t)pos);
if (m_derive == DeriveType::HARDENED) info.path.push_back(((uint32_t)pos) | 0x80000000L); if (m_derive == DeriveType::HARDENED_RANGED) info.path.push_back(((uint32_t)pos) | 0x80000000L);
// Derive keys or fetch them from cache // Derive keys or fetch them from cache
CExtPubKey final_extkey = m_root_extkey; CExtPubKey final_extkey = m_root_extkey;
@@ -436,19 +436,19 @@ public:
bool der = true; bool der = true;
if (read_cache) { if (read_cache) {
if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) { if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
if (m_derive == DeriveType::HARDENED) return std::nullopt; if (m_derive == DeriveType::HARDENED_RANGED) return std::nullopt;
// Try to get the derivation parent // Try to get the derivation parent
if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return std::nullopt; if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey)) return std::nullopt;
final_extkey = parent_extkey; final_extkey = parent_extkey;
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos); if (m_derive == DeriveType::UNHARDENED_RANGED) der = parent_extkey.Derive(final_extkey, pos);
} }
} else if (IsHardened()) { } else if (IsHardened()) {
CExtKey xprv; CExtKey xprv;
CExtKey lh_xprv; CExtKey lh_xprv;
if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return std::nullopt; if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return std::nullopt;
parent_extkey = xprv.Neuter(); parent_extkey = xprv.Neuter();
if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos); if (m_derive == DeriveType::UNHARDENED_RANGED) der = xprv.Derive(xprv, pos);
if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL); if (m_derive == DeriveType::HARDENED_RANGED) der = xprv.Derive(xprv, pos | 0x80000000UL);
final_extkey = xprv.Neuter(); final_extkey = xprv.Neuter();
if (lh_xprv.key.IsValid()) { if (lh_xprv.key.IsValid()) {
last_hardened_extkey = lh_xprv.Neuter(); last_hardened_extkey = lh_xprv.Neuter();
@@ -458,8 +458,8 @@ public:
if (!parent_extkey.Derive(parent_extkey, entry)) return std::nullopt; if (!parent_extkey.Derive(parent_extkey, entry)) return std::nullopt;
} }
final_extkey = parent_extkey; final_extkey = parent_extkey;
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos); if (m_derive == DeriveType::UNHARDENED_RANGED) der = parent_extkey.Derive(final_extkey, pos);
assert(m_derive != DeriveType::HARDENED); assert(m_derive != DeriveType::HARDENED_RANGED);
} }
if (!der) return std::nullopt; if (!der) return std::nullopt;
@@ -468,7 +468,7 @@ public:
if (write_cache) { if (write_cache) {
// Only cache parent if there is any unhardened derivation // Only cache parent if there is any unhardened derivation
if (m_derive != DeriveType::HARDENED) { if (m_derive != DeriveType::HARDENED_RANGED) {
write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey); write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
// Cache last hardened xpub if we have it // Cache last hardened xpub if we have it
if (last_hardened_extkey.pubkey.IsValid()) { if (last_hardened_extkey.pubkey.IsValid()) {
@@ -488,7 +488,7 @@ public:
std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path, /*apostrophe=*/use_apostrophe); std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path, /*apostrophe=*/use_apostrophe);
if (IsRange()) { if (IsRange()) {
ret += "/*"; ret += "/*";
if (m_derive == DeriveType::HARDENED) ret += use_apostrophe ? '\'' : 'h'; if (m_derive == DeriveType::HARDENED_RANGED) ret += use_apostrophe ? '\'' : 'h';
} }
return ret; return ret;
} }
@@ -506,13 +506,13 @@ public:
out = EncodeExtKey(key) + FormatHDKeypath(m_path, /*apostrophe=*/m_apostrophe); out = EncodeExtKey(key) + FormatHDKeypath(m_path, /*apostrophe=*/m_apostrophe);
if (IsRange()) { if (IsRange()) {
out += "/*"; out += "/*";
if (m_derive == DeriveType::HARDENED) out += m_apostrophe ? '\'' : 'h'; if (m_derive == DeriveType::HARDENED_RANGED) out += m_apostrophe ? '\'' : 'h';
} }
return true; return true;
} }
bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override
{ {
if (m_derive == DeriveType::HARDENED) { if (m_derive == DeriveType::HARDENED_RANGED) {
out = ToString(StringType::PUBLIC, /*normalized=*/true); out = ToString(StringType::PUBLIC, /*normalized=*/true);
return true; return true;
@@ -564,7 +564,7 @@ public:
out = "[" + origin_str + "]" + EncodeExtPubKey(xpub) + FormatHDKeypath(end_path); out = "[" + origin_str + "]" + EncodeExtPubKey(xpub) + FormatHDKeypath(end_path);
if (IsRange()) { if (IsRange()) {
out += "/*"; out += "/*";
assert(m_derive == DeriveType::UNHARDENED); assert(m_derive == DeriveType::UNHARDENED_RANGED);
} }
return true; return true;
} }
@@ -573,8 +573,8 @@ public:
CExtKey extkey; CExtKey extkey;
CExtKey dummy; CExtKey dummy;
if (!GetDerivedExtKey(arg, extkey, dummy)) return; if (!GetDerivedExtKey(arg, extkey, dummy)) return;
if (m_derive == DeriveType::UNHARDENED && !extkey.Derive(extkey, pos)) return; if (m_derive == DeriveType::UNHARDENED_RANGED && !extkey.Derive(extkey, pos)) return;
if (m_derive == DeriveType::HARDENED && !extkey.Derive(extkey, pos | 0x80000000UL)) return; if (m_derive == DeriveType::HARDENED_RANGED && !extkey.Derive(extkey, pos | 0x80000000UL)) return;
out.keys.emplace(extkey.key.GetPubKey().GetID(), extkey.key); out.keys.emplace(extkey.key.GetPubKey().GetID(), extkey.key);
} }
std::optional<CPubKey> GetRootPubKey() const override std::optional<CPubKey> GetRootPubKey() const override
@@ -605,7 +605,7 @@ private:
const DeriveType m_derive; const DeriveType m_derive;
const bool m_ranged_participants; const bool m_ranged_participants;
bool IsRangedDerivation() const { return m_derive != DeriveType::NO; } bool IsRangedDerivation() const { return m_derive != DeriveType::NON_RANGED; }
public: public:
MuSigPubkeyProvider( MuSigPubkeyProvider(
@@ -623,7 +623,7 @@ public:
if (!Assume(!(m_ranged_participants && IsRangedDerivation()))) { if (!Assume(!(m_ranged_participants && IsRangedDerivation()))) {
throw std::runtime_error("musig(): Cannot have both ranged participants and ranged derivation"); throw std::runtime_error("musig(): Cannot have both ranged participants and ranged derivation");
} }
if (!Assume(m_derive != DeriveType::HARDENED)) { if (!Assume(m_derive != DeriveType::HARDENED_RANGED)) {
throw std::runtime_error("musig(): Cannot have hardened derivation"); throw std::runtime_error("musig(): Cannot have hardened derivation");
} }
} }
@@ -1820,14 +1820,14 @@ std::optional<uint32_t> ParseKeyPathNum(std::span<const char> elem, bool& apostr
static DeriveType ParseDeriveType(std::vector<std::span<const char>>& split, bool& apostrophe) static DeriveType ParseDeriveType(std::vector<std::span<const char>>& split, bool& apostrophe)
{ {
DeriveType type = DeriveType::NO; DeriveType type = DeriveType::NON_RANGED;
if (std::ranges::equal(split.back(), std::span{"*"}.first(1))) { if (std::ranges::equal(split.back(), std::span{"*"}.first(1))) {
split.pop_back(); split.pop_back();
type = DeriveType::UNHARDENED; type = DeriveType::UNHARDENED_RANGED;
} else if (std::ranges::equal(split.back(), std::span{"*'"}.first(2)) || std::ranges::equal(split.back(), std::span{"*h"}.first(2))) { } else if (std::ranges::equal(split.back(), std::span{"*'"}.first(2)) || std::ranges::equal(split.back(), std::span{"*h"}.first(2))) {
apostrophe = std::ranges::equal(split.back(), std::span{"*'"}.first(2)); apostrophe = std::ranges::equal(split.back(), std::span{"*'"}.first(2));
split.pop_back(); split.pop_back();
type = DeriveType::HARDENED; type = DeriveType::HARDENED_RANGED;
} }
return type; return type;
} }
@@ -1969,7 +1969,7 @@ std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t& key_exp_index
} }
// Parse any derivation // Parse any derivation
DeriveType deriv_type = DeriveType::NO; DeriveType deriv_type = DeriveType::NON_RANGED;
std::vector<KeyPath> derivation_multipaths; std::vector<KeyPath> derivation_multipaths;
if (split.size() == 2 && Const("/", split.at(1), /*skip=*/false)) { if (split.size() == 2 && Const("/", split.at(1), /*skip=*/false)) {
if (!all_bip32) { if (!all_bip32) {
@@ -1983,7 +1983,7 @@ std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t& key_exp_index
bool dummy = false; bool dummy = false;
auto deriv_split = Split(split.at(1), '/'); auto deriv_split = Split(split.at(1), '/');
deriv_type = ParseDeriveType(deriv_split, dummy); deriv_type = ParseDeriveType(deriv_split, dummy);
if (deriv_type == DeriveType::HARDENED) { if (deriv_type == DeriveType::HARDENED_RANGED) {
error = "musig(): Cannot have hardened child derivation"; error = "musig(): Cannot have hardened child derivation";
return {}; return {};
} }