85 uint64_t
PolyMod(uint64_t c,
int val)
88 c = ((c & 0x7ffffffff) << 5) ^ val;
89 if (c0 & 1) c ^= 0xf5dee51989;
90 if (c0 & 2) c ^= 0xa9fdca3312;
91 if (c0 & 4) c ^= 0x1bab10e32d;
92 if (c0 & 8) c ^= 0x3706b1677a;
93 if (c0 & 16) c ^= 0x644d626ffd;
112 static std::string INPUT_CHARSET =
113 "0123456789()[],'/*abcdefgh@:$%{}" 114 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 115 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
118 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
123 for (
auto ch : span) {
124 auto pos = INPUT_CHARSET.find(ch);
125 if (pos == std::string::npos)
return "";
127 cls = cls * 3 + (pos >> 5);
128 if (++clscount == 3) {
135 if (clscount > 0) c =
PolyMod(c, cls);
136 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
139 std::string
ret(8,
' ');
140 for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
144 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
150 typedef std::vector<uint32_t> KeyPath;
153 struct PubkeyProvider
158 uint32_t m_expr_index;
161 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
163 virtual ~PubkeyProvider() =
default;
168 bool operator<(PubkeyProvider& other)
const {
174 other.GetPubKey(0, dummy, b, dummy_info);
187 virtual bool IsRange()
const = 0;
190 virtual size_t GetSize()
const = 0;
193 virtual std::string
ToString()
const = 0;
196 virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const = 0;
205 class OriginPubkeyProvider final :
public PubkeyProvider
208 std::unique_ptr<PubkeyProvider> m_provider;
210 std::string OriginString()
const 216 OriginPubkeyProvider(uint32_t exp_index,
KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(
std::move(info)), m_provider(
std::move(provider)) {}
219 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
220 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
221 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
224 bool IsRange()
const override {
return m_provider->IsRange(); }
225 size_t GetSize()
const override {
return m_provider->GetSize(); }
226 std::string
ToString()
const override {
return "[" + OriginString() +
"]" + m_provider->ToString(); }
230 if (!m_provider->ToPrivateString(arg, sub))
return false;
231 ret =
"[" + OriginString() +
"]" + std::move(sub);
237 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
243 ret =
"[" + OriginString() + std::move(sub);
245 ret =
"[" + OriginString() +
"]" + std::move(sub);
251 return m_provider->GetPrivKey(pos, arg, key);
256 class ConstPubkeyProvider final :
public PubkeyProvider
262 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
267 CKeyID keyid = m_pubkey.GetID();
271 bool IsRange()
const override {
return false; }
272 size_t GetSize()
const override {
return m_pubkey.size(); }
273 std::string
ToString()
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
278 for (
const auto& keyid :
XOnlyPubKey(m_pubkey).GetKeyIDs()) {
283 arg.
GetKey(m_pubkey.GetID(), key);
285 if (!key.
IsValid())
return false;
296 return arg.
GetKey(m_pubkey.GetID(), key);
307 class BIP32PubkeyProvider final :
public PubkeyProvider
317 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
318 ret.nDepth = m_root_extkey.nDepth;
319 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
320 ret.nChild = m_root_extkey.nChild;
321 ret.chaincode = m_root_extkey.chaincode;
329 if (!GetExtKey(arg, xprv))
return false;
330 for (
auto entry : m_path) {
331 if (!xprv.
Derive(xprv, entry))
return false;
333 last_hardened = xprv;
339 bool IsHardened()
const 341 if (m_derive == DeriveType::HARDENED)
return true;
342 for (
auto entry : m_path) {
343 if (entry >> 31)
return true;
349 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey& extkey, KeyPath path,
DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(
std::move(path)), m_derive(derive) {}
350 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
351 size_t GetSize()
const override {
return 33; }
356 CKeyID keyid = m_root_extkey.pubkey.GetID();
358 parent_info.
path = m_path;
362 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
363 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
371 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
372 if (m_derive == DeriveType::HARDENED)
return false;
374 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
375 final_extkey = parent_extkey;
376 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
378 }
else if (IsHardened()) {
381 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
382 parent_extkey = xprv.
Neuter();
383 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
384 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
385 final_extkey = xprv.
Neuter();
387 last_hardened_extkey = lh_xprv.
Neuter();
390 for (
auto entry : m_path) {
391 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
393 final_extkey = parent_extkey;
394 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
395 assert(m_derive != DeriveType::HARDENED);
397 if (!der)
return false;
399 final_info_out = final_info_out_tmp;
400 key_out = final_extkey.
pubkey;
404 if (m_derive != DeriveType::HARDENED) {
405 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
408 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
410 }
else if (final_info_out.
path.size() > 0) {
411 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
417 std::string
ToString()
const override 422 if (m_derive == DeriveType::HARDENED)
ret +=
'\'';
426 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const override 429 if (!GetExtKey(arg, key))
return false;
433 if (m_derive == DeriveType::HARDENED) out +=
'\'';
440 if (m_derive == DeriveType::HARDENED) {
445 int i = (int)m_path.size() - 1;
446 for (; i >= 0; --i) {
447 if (m_path.at(i) >> 31) {
459 for (;
k <= i; ++
k) {
461 origin.
path.push_back(m_path.at(
k));
465 for (;
k < (int)m_path.size(); ++
k) {
466 end_path.push_back(m_path.at(
k));
469 CKeyID id = m_root_extkey.pubkey.GetID();
470 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
475 if (cache !=
nullptr) {
481 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
491 assert(m_derive == DeriveType::UNHARDENED);
499 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
500 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
501 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
512 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
514 const std::string m_name;
520 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
523 virtual std::string ToStringExtra()
const {
return ""; }
538 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
539 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args(
Vector(
std::move(script))) {}
540 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::vector<std::unique_ptr<DescriptorImpl>> scripts,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args(
std::move(scripts)) {}
542 enum class StringType
551 for (
const auto& arg : m_subdescriptor_args) {
552 if (!arg->IsSolvable())
return false;
559 for (
const auto& pubkey : m_pubkey_args) {
560 if (pubkey->IsRange())
return true;
562 for (
const auto& arg : m_subdescriptor_args) {
563 if (arg->IsRange())
return true;
571 for (
const auto& scriptarg : m_subdescriptor_args) {
572 if (pos++)
ret +=
",";
574 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
582 std::string extra = ToStringExtra();
583 size_t pos = extra.size() > 0 ? 1 : 0;
584 std::string
ret = m_name +
"(" + extra;
585 for (
const auto& pubkey : m_pubkey_args) {
586 if (pos++)
ret +=
",";
589 case StringType::NORMALIZED:
590 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
592 case StringType::PRIVATE:
593 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
595 case StringType::PUBLIC:
596 tmp = pubkey->ToString();
601 std::string subscript;
602 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
603 if (pos && subscript.size())
ret +=
',';
604 out = std::move(
ret) + std::move(subscript) +
")";
611 ToStringHelper(
nullptr,
ret, StringType::PUBLIC);
612 return AddChecksum(
ret);
617 bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
618 out = AddChecksum(out);
624 bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
625 out = AddChecksum(out);
631 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
632 entries.reserve(m_pubkey_args.size());
635 for (
const auto& p : m_pubkey_args) {
636 entries.emplace_back();
637 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
639 std::vector<CScript> subscripts;
641 for (
const auto& subarg : m_subdescriptor_args) {
642 std::vector<CScript> outscripts;
643 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
644 assert(outscripts.size() == 1);
645 subscripts.emplace_back(std::move(outscripts[0]));
647 out.
Merge(std::move(subprovider));
649 std::vector<CPubKey> pubkeys;
650 pubkeys.reserve(entries.size());
651 for (
auto& entry : entries) {
652 pubkeys.push_back(entry.first);
653 out.
origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
656 output_scripts = MakeScripts(pubkeys,
Span{subscripts}, out);
662 return ExpandHelper(pos, provider,
nullptr, output_scripts, out, write_cache);
672 for (
const auto& p : m_pubkey_args) {
674 if (!p->GetPrivKey(pos, provider, key))
continue;
677 for (
const auto& arg : m_subdescriptor_args) {
678 arg->ExpandPrivate(pos, provider, out);
682 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
686 class AddressDescriptor final :
public DescriptorImpl
690 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
693 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
694 bool IsSolvable() const final {
return false; }
700 bool IsSingleType() const final {
return true; }
701 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final {
return false; }
705 class RawDescriptor final :
public DescriptorImpl
709 std::string ToStringExtra()
const override {
return HexStr(m_script); }
712 RawDescriptor(
CScript script) : DescriptorImpl({},
"raw"), m_script(std::move(script)) {}
713 bool IsSolvable() const final {
return false; }
721 bool IsSingleType() const final {
return true; }
722 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final {
return false; }
726 class PKDescriptor final :
public DescriptorImpl
735 return Vector(std::move(script));
741 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
742 bool IsSingleType() const final {
return true; }
746 class PKHDescriptor final :
public DescriptorImpl
751 CKeyID id = keys[0].GetID();
752 out.
pubkeys.emplace(
id, keys[0]);
756 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
758 bool IsSingleType() const final {
return true; }
762 class WPKHDescriptor final :
public DescriptorImpl
767 CKeyID id = keys[0].GetID();
768 out.
pubkeys.emplace(
id, keys[0]);
772 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
774 bool IsSingleType() const final {
return true; }
778 class ComboDescriptor final :
public DescriptorImpl
783 std::vector<CScript>
ret;
784 CKeyID id = keys[0].GetID();
785 out.
pubkeys.emplace(
id, keys[0]);
788 if (keys[0].IsCompressed()) {
791 ret.emplace_back(p2wpkh);
797 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
798 bool IsSingleType() const final {
return false; }
802 class MultisigDescriptor final :
public DescriptorImpl
804 const int m_threshold;
807 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
810 std::vector<CPubKey> sorted_keys(keys);
811 std::sort(sorted_keys.begin(), sorted_keys.end());
817 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) {}
818 bool IsSingleType() const final {
return true; }
822 class MultiADescriptor final :
public DescriptorImpl
824 const int m_threshold;
827 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
830 std::vector<XOnlyPubKey> xkeys;
831 for (
const auto& key : keys) xkeys.emplace_back(key);
832 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
834 for (
size_t i = 1; i < keys.size(); ++i) {
841 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) {}
842 bool IsSingleType() const final {
return true; }
846 class SHDescriptor final :
public DescriptorImpl
856 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
860 assert(m_subdescriptor_args.size() == 1);
864 bool IsSingleType() const final {
return true; }
868 class WSHDescriptor final :
public DescriptorImpl
878 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
880 bool IsSingleType() const final {
return true; }
884 class TRDescriptor final :
public DescriptorImpl
886 std::vector<int> m_depths;
892 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
898 if (!xpk.IsFullyValid())
return {};
902 out.
pubkeys.emplace(keys[0].GetID(), keys[0]);
907 if (m_depths.empty())
return true;
908 std::vector<bool> path;
909 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
911 while ((
int)path.size() <= m_depths[pos]) {
912 if (path.size())
ret +=
'{';
913 path.push_back(
false);
916 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
918 while (!path.empty() && path.back()) {
919 if (path.size() > 1)
ret +=
'}';
922 if (!path.empty()) path.back() =
true;
927 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
928 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
930 assert(m_subdescriptor_args.size() == m_depths.size());
933 bool IsSingleType() const final {
return true; }
946 const std::vector<CPubKey>& m_keys;
949 ScriptMaker(
const std::vector<CPubKey>& keys
LIFETIMEBOUND) : m_keys(keys) {}
951 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
952 return {m_keys[key].begin(), m_keys[key].end()};
955 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
956 auto id = m_keys[key].GetID();
957 return {
id.begin(),
id.end()};
968 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
974 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
976 std::optional<std::string>
ToString(uint32_t key)
const 980 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
982 ret = m_pubkeys[key]->ToString();
988 class MiniscriptDescriptor final :
public DescriptorImpl
994 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys,
Span<const CScript> scripts,
997 for (
const auto& key : keys) provider.
pubkeys.emplace(key.GetID(), key);
1005 bool ToStringHelper(
const SigningProvider* arg, std::string& out,
const StringType type,
1008 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1015 bool IsSolvable()
const override {
return false; }
1016 bool IsSingleType() const final {
return true; }
1020 class RawTRDescriptor final :
public DescriptorImpl
1025 assert(keys.size() == 1);
1027 if (!xpk.IsFullyValid())
return {};
1032 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1034 bool IsSingleType() const final {
return true; }
1050 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath& out, std::string&
error)
1052 for (
size_t i = 1; i < split.size(); ++i) {
1054 bool hardened =
false;
1055 if (elem.
size() > 0 && (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
1063 }
else if (p > 0x7FFFFFFFUL) {
1067 out.push_back(p | (((uint32_t)hardened) << 31));
1077 bool permit_uncompressed =
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH;
1078 auto split =
Split(sp,
'/');
1079 std::string str(split[0].begin(), split[0].end());
1080 if (str.size() == 0) {
1081 error =
"No key provided";
1084 if (split.size() == 1) {
1086 std::vector<unsigned char> data =
ParseHex(str);
1088 if (pubkey.IsFullyValid()) {
1089 if (permit_uncompressed || pubkey.IsCompressed()) {
1090 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false);
1092 error =
"Uncompressed keys are not allowed";
1095 }
else if (data.size() == 32 &&
ctx == ParseScriptContext::P2TR) {
1096 unsigned char fullkey[33] = {0x02};
1097 std::copy(data.begin(), data.end(), fullkey + 1);
1098 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1099 if (pubkey.IsFullyValid()) {
1100 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true);
1111 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
ctx == ParseScriptContext::P2TR);
1113 error =
"Uncompressed keys are not allowed";
1126 if (split.back() ==
Span{
"*"}.
first(1)) {
1128 type = DeriveType::UNHARDENED;
1129 }
else if (split.back() ==
Span{
"*'"}.
first(2) || split.back() ==
Span{
"*h"}.
first(2)) {
1131 type = DeriveType::HARDENED;
1133 if (!ParseKeyPath(split, path,
error))
return nullptr;
1135 extpubkey = extkey.
Neuter();
1138 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
1146 auto origin_split =
Split(sp,
']');
1147 if (origin_split.size() > 2) {
1148 error =
"Multiple ']' characters found for a single pubkey";
1151 if (origin_split.size() == 1)
return ParsePubkeyInner(key_exp_index, origin_split[0],
ctx, out,
error);
1152 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1153 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1154 origin_split[0].empty() ?
']' : origin_split[0][0]);
1157 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1158 if (slash_split[0].size() != 8) {
1159 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1162 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1163 if (!
IsHex(fpr_hex)) {
1167 auto fpr_bytes =
ParseHex(fpr_hex);
1169 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1170 assert(fpr_bytes.size() == 4);
1171 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1172 if (!ParseKeyPath(slash_split, info.
path,
error))
return nullptr;
1173 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1],
ctx, out,
error);
1174 if (!provider)
return nullptr;
1175 return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
1180 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1183 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1185 return key_provider;
1191 std::copy(xkey.
begin(), xkey.
end(), full_key + 1);
1193 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1196 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1198 return key_provider;
1206 using Key = uint32_t;
1212 mutable std::vector<std::unique_ptr<PubkeyProvider>> m_keys;
1214 mutable std::string m_key_parsing_error;
1218 bool KeyCompare(
const Key& a,
const Key& b)
const {
1219 return *m_keys.at(a) < *m_keys.at(b);
1222 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const 1225 Key key = m_keys.
size();
1226 auto pk = ParsePubkey(key, {&*begin, &*end}, ParseScriptContext::P2WSH, *m_out, m_key_parsing_error);
1228 m_keys.push_back(std::move(pk));
1232 std::optional<std::string>
ToString(
const Key& key)
const 1234 return m_keys.at(key)->ToString();
1237 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const 1241 if (pubkey.IsValid()) {
1242 Key key = m_keys.size();
1243 m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
1249 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const 1251 assert(end - begin == 20);
1254 std::copy(begin, end, hash.
begin());
1258 Key key = m_keys.
size();
1259 m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
1271 auto expr =
Expr(sp);
1272 if (
Func(
"pk", expr)) {
1273 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1279 return std::make_unique<PKDescriptor>(std::move(pubkey),
ctx == ParseScriptContext::P2TR);
1281 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1282 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1288 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1289 }
else if (
Func(
"pkh", expr)) {
1290 error =
"Can only have pkh at top level, in sh(), or in wsh()";
1293 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1294 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1300 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1301 }
else if (
Func(
"combo", expr)) {
1302 error =
"Can only have combo() at top level";
1305 const bool multi =
Func(
"multi", expr);
1306 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1307 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1308 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1309 if (((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1310 (
ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1311 auto threshold =
Expr(expr);
1313 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1314 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1315 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1318 size_t script_size = 0;
1319 while (expr.size()) {
1320 if (!
Const(
",", expr)) {
1324 auto arg =
Expr(expr);
1325 auto pk = ParsePubkey(key_exp_index, arg,
ctx, out,
error);
1330 script_size += pk->GetSize() + 1;
1331 providers.emplace_back(std::move(pk));
1340 }
else if (thres < 1) {
1341 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1343 }
else if (thres > providers.size()) {
1344 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1347 if (
ctx == ParseScriptContext::TOP) {
1348 if (providers.size() > 3) {
1349 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1353 if (
ctx == ParseScriptContext::P2SH) {
1360 if (multi || sortedmulti) {
1361 return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sortedmulti);
1363 return std::make_unique<MultiADescriptor>(thres, std::move(providers), sortedmulti_a);
1365 }
else if (multi || sortedmulti) {
1366 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1368 }
else if (multi_a || sortedmulti_a) {
1369 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1372 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1373 auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out,
error);
1379 return std::make_unique<WPKHDescriptor>(std::move(pubkey));
1380 }
else if (
Func(
"wpkh", expr)) {
1381 error =
"Can only have wpkh() at top level or inside sh()";
1384 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1385 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out,
error);
1386 if (!desc || expr.size())
return nullptr;
1387 return std::make_unique<SHDescriptor>(std::move(desc));
1388 }
else if (
Func(
"sh", expr)) {
1389 error =
"Can only have sh() at top level";
1392 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1393 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out,
error);
1394 if (!desc || expr.size())
return nullptr;
1395 return std::make_unique<WSHDescriptor>(std::move(desc));
1396 }
else if (
Func(
"wsh", expr)) {
1397 error =
"Can only have wsh() at top level or inside sh()";
1400 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1403 error =
"Address is not valid";
1406 return std::make_unique<AddressDescriptor>(std::move(dest));
1407 }
else if (
Func(
"addr", expr)) {
1408 error =
"Can only have addr() at top level";
1411 if (
ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1412 auto arg =
Expr(expr);
1413 auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out,
error);
1414 if (!internal_key) {
1419 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1420 std::vector<int> depths;
1422 if (!
Const(
",", expr)) {
1429 std::vector<bool> branches;
1434 while (
Const(
"{", expr)) {
1435 branches.push_back(
false);
1442 auto sarg =
Expr(expr);
1443 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR, out,
error));
1444 if (!subscripts.back())
return nullptr;
1445 depths.push_back(branches.size());
1447 while (branches.size() && branches.back()) {
1448 if (!
Const(
"}", expr)) {
1452 branches.pop_back();
1455 if (branches.size() && !branches.back()) {
1456 if (!
Const(
",", expr)) {
1460 branches.back() =
true;
1462 }
while (branches.size());
1470 return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
1471 }
else if (
Func(
"tr", expr)) {
1472 error =
"Can only have tr at top level";
1475 if (
ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
1476 auto arg =
Expr(expr);
1481 auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out,
error);
1482 if (!output_key)
return nullptr;
1484 return std::make_unique<RawTRDescriptor>(std::move(output_key));
1485 }
else if (
Func(
"rawtr", expr)) {
1486 error =
"Can only have rawtr at top level";
1489 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1490 std::string str(expr.begin(), expr.end());
1492 error =
"Raw script is not hex";
1496 return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
1497 }
else if (
Func(
"raw", expr)) {
1498 error =
"Can only have raw() at top level";
1503 KeyParser parser(&out,
nullptr);
1506 if (
ctx != ParseScriptContext::P2WSH) {
1507 error =
"Miniscript expressions can only be used in wsh";
1510 if (parser.m_key_parsing_error !=
"") {
1511 error = std::move(parser.m_key_parsing_error);
1514 if (!
node->IsSane()) {
1516 auto insane_node =
node.get();
1517 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
1518 if (
const auto str = insane_node->ToString(parser))
error = *str;
1519 if (!insane_node->IsValid()) {
1520 error +=
" is invalid";
1522 error +=
" is not sane";
1523 if (!insane_node->IsNonMalleable()) {
1524 error +=
": malleable witnesses exist";
1525 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
1526 error +=
": witnesses without signature exist";
1527 }
else if (!insane_node->CheckTimeLocksMix()) {
1528 error +=
": contains mixes of timelocks expressed in blocks and seconds";
1529 }
else if (!insane_node->CheckDuplicateKey()) {
1530 error +=
": contains duplicate public keys";
1531 }
else if (!insane_node->ValidSatisfactions()) {
1532 error +=
": needs witnesses that may exceed resource limits";
1537 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1540 if (
ctx == ParseScriptContext::P2SH) {
1541 error =
"A function is needed within P2SH";
1543 }
else if (
ctx == ParseScriptContext::P2WSH) {
1544 error =
"A function is needed within P2WSH";
1547 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
1554 if (!match)
return {};
1555 std::vector<std::unique_ptr<PubkeyProvider>> keys;
1556 keys.reserve(match->second.size());
1557 for (
const auto keyspan : match->second) {
1558 if (keyspan.size() != 32)
return {};
1559 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan},
ctx, provider);
1560 if (!key)
return {};
1561 keys.push_back(std::move(key));
1563 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
1568 if (
ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] ==
OP_CHECKSIG) {
1570 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key,
ctx, provider),
true);
1573 if (
ctx == ParseScriptContext::P2TR) {
1574 auto ret = InferMultiA(script,
ctx, provider);
1578 std::vector<std::vector<unsigned char>> data;
1581 if (txntype ==
TxoutType::PUBKEY && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1584 return std::make_unique<PKDescriptor>(InferPubkey(pubkey,
ctx, provider));
1587 if (txntype ==
TxoutType::PUBKEYHASH && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1591 if (provider.
GetPubKey(keyid, pubkey)) {
1592 return std::make_unique<PKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1599 if (provider.
GetPubKey(keyid, pubkey)) {
1600 return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1603 if (txntype ==
TxoutType::MULTISIG && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1604 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1605 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1607 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1609 return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1615 if (provider.
GetCScript(scriptid, subscript)) {
1616 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1617 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1624 if (provider.
GetCScript(scriptid, subscript)) {
1625 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1626 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1632 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1641 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1642 std::vector<int> depths;
1643 for (
const auto& [depth, script, leaf_ver] : *tree) {
1644 std::unique_ptr<DescriptorImpl> subdesc;
1646 subdesc = InferScript(script, ParseScriptContext::P2TR, provider);
1652 subscripts.push_back(std::move(subdesc));
1653 depths.push_back(depth);
1657 auto key = InferXOnlyPubkey(tap.internal_key, ParseScriptContext::P2TR, provider);
1658 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
1664 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
1666 return std::make_unique<RawTRDescriptor>(std::move(key));
1671 if (
ctx == ParseScriptContext::P2WSH) {
1672 KeyParser parser(
nullptr, &provider);
1675 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1682 return std::make_unique<AddressDescriptor>(std::move(dest));
1686 return std::make_unique<RawDescriptor>(script);
1697 auto check_split =
Split(sp,
'#');
1698 if (check_split.size() > 2) {
1699 error =
"Multiple '#' symbols";
1702 if (check_split.size() == 1 && require_checksum){
1703 error =
"Missing checksum";
1706 if (check_split.size() == 2) {
1707 if (check_split[1].size() != 8) {
1708 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
1712 auto checksum = DescriptorChecksum(check_split[0]);
1713 if (checksum.empty()) {
1714 error =
"Invalid characters in payload";
1717 if (check_split.size() == 2) {
1718 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1719 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1723 if (out_checksum) *out_checksum = std::move(checksum);
1724 sp = check_split[0];
1732 uint32_t key_exp_index = 0;
1734 if (sp.
size() == 0 &&
ret)
return std::unique_ptr<Descriptor>(std::move(
ret));
1749 return InferScript(script, ParseScriptContext::TOP, provider);
1760 xpubs[der_index] = xpub;
1780 const auto& der_it = key_exp_it->second.find(der_index);
1781 if (der_it == key_exp_it->second.end())
return false;
1782 xpub = der_it->second;
1800 if (xpub != parent_xpub_pair.second) {
1801 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
1809 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
1812 if (xpub != derived_xpub_pair.second) {
1813 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
1817 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1818 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1824 if (xpub != lh_xpub_pair.second) {
1825 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
bool CheckChecksum(Span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
std::vector< T > Split(const Span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
constexpr C * end() const noexcept
bool Derive(CExtKey &out, unsigned int nChild) const
CPubKey GetPubKey() const
Compute the public key from a private key.
std::map< CKeyID, CKey > keys
CExtKey DecodeExtKey(const std::string &str)
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
bool IsHex(std::string_view str)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
constexpr std::size_t size() const noexcept
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys...
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened xpub.
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
std::optional< std::vector< std::tuple< int, CScript, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
static const int MAX_PUBKEYS_PER_MULTISIG
CExtPubKey DecodeExtPubKey(const std::string &str)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
std::shared_ptr< const Node< Key > > NodeRef
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
virtual std::string ToString() const =0
Convert the descriptor back to a string, undoing parsing.
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
std::vector< Byte > ParseHex(std::string_view str)
Parse the hex string into bytes (uint8_t or std::byte).
static constexpr unsigned int COMPRESSED_SIZE
const unsigned char * begin() const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::map< CScriptID, CScript > scripts
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
const SigningProvider & DUMMY_SIGNING_PROVIDER
TaprootBuilder & Add(int depth, const CScript &script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
static secp256k1_context * ctx
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
An encapsulated public key.
std::map< CKeyID, CPubKey > pubkeys
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
unsigned int size() const
Simple read-only vector-like interface.
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
bool IsFullyValid() const
Determine if this pubkey is fully valid.
virtual bool GetKey(const CKeyID &address, CKey &key) const
FlatSigningProvider & Merge(FlatSigningProvider &&b) LIFETIMEBOUND
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Utility class to construct Taproot outputs from internal key and script tree.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
bool operator<(const CNetAddr &a, const CNetAddr &b)
void PolyMod(const std::vector< typename F::Elem > &mod, std::vector< typename F::Elem > &val, const F &field)
Compute the remainder of a polynomial division of val by mod, putting the result in mod...
constexpr C * begin() const noexcept
std::vector< unsigned char > ToByteVector(const T &in)
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) const =0
Expand a descriptor at a specified position.
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
bool Derive(CExtPubKey &out, unsigned int nChild) const
std::string EncodeExtPubKey(const CExtPubKey &key)
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
An interface to be implemented by keystores that support signing.
CExtPubKey Neuter() const
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
Cache for single descriptor's derived extended pubkeys.
Serialized script, used inside transaction inputs and outputs.
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
std::optional< std::pair< int, std::vector< Span< const unsigned char > > > > MatchMultiA(const CScript &script)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
A reference to a CKey: the Hash160 of its serialized public key.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
A reference to a CScript: the Hash160 of its serialization (see script.h)
std::string EncodeDestination(const CTxDestination &dest)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
An encapsulated private key.
A Span is an object that can refer to a contiguous sequence of objects.
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
CKey DecodeSecret(const std::string &str)
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
void Finalize(unsigned char hash[OUTPUT_SIZE])
virtual std::optional< OutputType > GetOutputType() const =0
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
CScript ParseScript(const std::string &s)
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
std::string EncodeSecret(const CKey &key)
std::vector< uint32_t > path
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
const unsigned char * end() const
bool error(const char *fmt, const Args &... args)
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
std::string EncodeExtKey(const CExtKey &key)
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
Interface for parsed descriptor objects.
A hasher class for RIPEMD-160.
bool IsValid() const
Check whether this private key is valid.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::map< XOnlyPubKey, TaprootBuilder > tr_trees