Skip to content

Commit 16f8054

Browse files
committed
descriptor: Add CanSelfExpand()
CanSelfExpand() reports whether a descriptor can be expanded without needing any caches or private keys to be provided by the caller of Expand().
1 parent 2723625 commit 16f8054

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/script/descriptor.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ struct PubkeyProvider
221221

222222
/** Make a deep copy of this PubkeyProvider */
223223
virtual std::unique_ptr<PubkeyProvider> Clone() const = 0;
224+
225+
/** Whether this PubkeyProvider can always provide a public key without cache or private key arguments */
226+
virtual bool CanSelfExpand() const = 0;
224227
};
225228

226229
class OriginPubkeyProvider final : public PubkeyProvider
@@ -290,6 +293,7 @@ class OriginPubkeyProvider final : public PubkeyProvider
290293
{
291294
return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
292295
}
296+
bool CanSelfExpand() const override { return m_provider->CanSelfExpand(); }
293297
};
294298

295299
/** An object representing a parsed constant public key in a descriptor. */
@@ -350,6 +354,7 @@ class ConstPubkeyProvider final : public PubkeyProvider
350354
{
351355
return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
352356
}
357+
bool CanSelfExpand() const final { return true; }
353358
};
354359

355360
enum class DeriveType {
@@ -572,6 +577,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
572577
{
573578
return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
574579
}
580+
bool CanSelfExpand() const override { return !IsHardened(); }
575581
};
576582

577583
/** Base class for all Descriptor implementations. */
@@ -800,6 +806,7 @@ class AddressDescriptor final : public DescriptorImpl
800806
}
801807
bool IsSingleType() const final { return true; }
802808
bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
809+
bool CanSelfExpand() const final { return true; }
803810

804811
std::optional<int64_t> ScriptSize() const override { return GetScriptForDestination(m_destination).size(); }
805812
std::unique_ptr<DescriptorImpl> Clone() const override
@@ -827,6 +834,7 @@ class RawDescriptor final : public DescriptorImpl
827834
}
828835
bool IsSingleType() const final { return true; }
829836
bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
837+
bool CanSelfExpand() const final { return true; }
830838

831839
std::optional<int64_t> ScriptSize() const override { return m_script.size(); }
832840

@@ -854,6 +862,7 @@ class PKDescriptor final : public DescriptorImpl
854862
public:
855863
PKDescriptor(std::unique_ptr<PubkeyProvider> prov, bool xonly = false) : DescriptorImpl(Vector(std::move(prov)), "pk"), m_xonly(xonly) {}
856864
bool IsSingleType() const final { return true; }
865+
bool CanSelfExpand() const override { return m_pubkey_args[0]->CanSelfExpand(); }
857866

858867
std::optional<int64_t> ScriptSize() const override {
859868
return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
@@ -889,6 +898,7 @@ class PKHDescriptor final : public DescriptorImpl
889898
PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "pkh") {}
890899
std::optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }
891900
bool IsSingleType() const final { return true; }
901+
bool CanSelfExpand() const override { return m_pubkey_args[0]->CanSelfExpand(); }
892902

893903
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 1 + 20 + 1 + 1; }
894904

@@ -922,6 +932,7 @@ class WPKHDescriptor final : public DescriptorImpl
922932
WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "wpkh") {}
923933
std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
924934
bool IsSingleType() const final { return true; }
935+
bool CanSelfExpand() const override { return m_pubkey_args[0]->CanSelfExpand(); }
925936

926937
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20; }
927938

@@ -963,6 +974,7 @@ class ComboDescriptor final : public DescriptorImpl
963974
public:
964975
ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "combo") {}
965976
bool IsSingleType() const final { return false; }
977+
bool CanSelfExpand() const override { return m_pubkey_args[0]->CanSelfExpand(); }
966978
std::unique_ptr<DescriptorImpl> Clone() const override
967979
{
968980
return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
@@ -987,6 +999,13 @@ class MultisigDescriptor final : public DescriptorImpl
987999
public:
9881000
MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}
9891001
bool IsSingleType() const final { return true; }
1002+
bool CanSelfExpand() const override {
1003+
bool can_expand = true;
1004+
for (const auto& key : m_pubkey_args) {
1005+
can_expand &= key->CanSelfExpand();
1006+
}
1007+
return can_expand;
1008+
}
9901009

9911010
std::optional<int64_t> ScriptSize() const override {
9921011
const auto n_keys = m_pubkey_args.size();
@@ -1038,6 +1057,13 @@ class MultiADescriptor final : public DescriptorImpl
10381057
public:
10391058
MultiADescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti_a" : "multi_a"), m_threshold(threshold), m_sorted(sorted) {}
10401059
bool IsSingleType() const final { return true; }
1060+
bool CanSelfExpand() const override {
1061+
bool can_expand = true;
1062+
for (const auto& key : m_pubkey_args) {
1063+
can_expand &= key->CanSelfExpand();
1064+
}
1065+
return can_expand;
1066+
}
10411067

10421068
std::optional<int64_t> ScriptSize() const override {
10431069
const auto n_keys = m_pubkey_args.size();
@@ -1084,6 +1110,7 @@ class SHDescriptor final : public DescriptorImpl
10841110
return OutputType::LEGACY;
10851111
}
10861112
bool IsSingleType() const final { return true; }
1113+
bool CanSelfExpand() const override { return m_subdescriptor_args[0]->CanSelfExpand(); }
10871114

10881115
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20 + 1; }
10891116

@@ -1125,6 +1152,7 @@ class WSHDescriptor final : public DescriptorImpl
11251152
WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
11261153
std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }
11271154
bool IsSingleType() const final { return true; }
1155+
bool CanSelfExpand() const override { return m_subdescriptor_args[0]->CanSelfExpand(); }
11281156

11291157
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
11301158

@@ -1202,6 +1230,13 @@ class TRDescriptor final : public DescriptorImpl
12021230
}
12031231
std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
12041232
bool IsSingleType() const final { return true; }
1233+
bool CanSelfExpand() const override {
1234+
bool can_expand = m_pubkey_args[0]->CanSelfExpand();
1235+
for (const auto& sub : m_subdescriptor_args) {
1236+
can_expand &= sub->CanSelfExpand();
1237+
}
1238+
return can_expand;
1239+
}
12051240

12061241
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
12071242

@@ -1329,6 +1364,13 @@ class MiniscriptDescriptor final : public DescriptorImpl
13291364

13301365
bool IsSolvable() const override { return true; }
13311366
bool IsSingleType() const final { return true; }
1367+
bool CanSelfExpand() const override {
1368+
bool can_expand = true;
1369+
for (const auto& key : m_pubkey_args) {
1370+
can_expand &= key->CanSelfExpand();
1371+
}
1372+
return can_expand;
1373+
}
13321374

13331375
std::optional<int64_t> ScriptSize() const override { return m_node->ScriptSize(); }
13341376

@@ -1368,6 +1410,7 @@ class RawTRDescriptor final : public DescriptorImpl
13681410
RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), "rawtr") {}
13691411
std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
13701412
bool IsSingleType() const final { return true; }
1413+
bool CanSelfExpand() const override { return m_pubkey_args[0]->CanSelfExpand(); }
13711414

13721415
std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 32; }
13731416

src/script/descriptor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ struct Descriptor {
117117
/** Convert the descriptor to a normalized string. Normalized descriptors have the xpub at the last hardened step. This fails if the provided provider does not have the private keys to derive that xpub. */
118118
virtual bool ToNormalizedString(const SigningProvider& provider, std::string& out, const DescriptorCache* cache = nullptr) const = 0;
119119

120+
/** Whether the descriptor can be used to get more addresses without needing a cache or private keys. */
121+
virtual bool CanSelfExpand() const = 0;
122+
120123
/** Expand a descriptor at a specified position.
121124
*
122125
* @param[in] pos The position at which to expand the descriptor. If IsRange() is false, this is ignored.

src/wallet/test/walletload_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class DummyDescriptor final : public Descriptor {
3535
std::optional<int64_t> MaxSatisfactionWeight(bool) const override { return {}; }
3636
std::optional<int64_t> MaxSatisfactionElems() const override { return {}; }
3737
void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs) const override {}
38+
bool CanSelfExpand() const final { return false; }
3839
};
3940

4041
BOOST_FIXTURE_TEST_CASE(wallet_load_descriptors, TestingSetup)

0 commit comments

Comments
 (0)