84 uint64_t PolyMod(uint64_t c,
int val)
87 c = ((c & 0x7ffffffff) << 5) ^ val;
88 if (c0 & 1) c ^= 0xf5dee51989;
89 if (c0 & 2) c ^= 0xa9fdca3312;
90 if (c0 & 4) c ^= 0x1bab10e32d;
91 if (c0 & 8) c ^= 0x3706b1677a;
92 if (c0 & 16) c ^= 0x644d626ffd;
111 static std::string INPUT_CHARSET =
112 "0123456789()[],'/*abcdefgh@:$%{}" 113 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 114 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
117 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
122 for (
auto ch : span) {
123 auto pos = INPUT_CHARSET.find(ch);
124 if (pos == std::string::npos)
return "";
125 c = PolyMod(c, pos & 31);
126 cls = cls * 3 + (pos >> 5);
127 if (++clscount == 3) {
134 if (clscount > 0) c = PolyMod(c, cls);
135 for (
int j = 0; j < 8; ++j) c = PolyMod(c, 0);
138 std::string ret(8,
' ');
139 for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
143 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
149 typedef std::vector<uint32_t> KeyPath;
152 struct PubkeyProvider
157 uint32_t m_expr_index;
160 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
162 virtual ~PubkeyProvider() =
default;
172 virtual bool IsRange()
const = 0;
175 virtual size_t GetSize()
const = 0;
178 virtual std::string
ToString()
const = 0;
181 virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const = 0;
190 class OriginPubkeyProvider final :
public PubkeyProvider
193 std::unique_ptr<PubkeyProvider> m_provider;
195 std::string OriginString()
const 201 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)) {}
204 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
205 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
206 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
209 bool IsRange()
const override {
return m_provider->IsRange(); }
210 size_t GetSize()
const override {
return m_provider->GetSize(); }
211 std::string
ToString()
const override {
return "[" + OriginString() +
"]" + m_provider->ToString(); }
212 bool ToPrivateString(
const SigningProvider& arg, std::string& ret)
const override 215 if (!m_provider->ToPrivateString(arg, sub))
return false;
216 ret =
"[" + OriginString() +
"]" + std::move(sub);
222 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
228 ret =
"[" + OriginString() + std::move(sub);
230 ret =
"[" + OriginString() +
"]" + std::move(sub);
236 return m_provider->GetPrivKey(pos, arg, key);
241 class ConstPubkeyProvider final :
public PubkeyProvider
247 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
252 CKeyID keyid = m_pubkey.GetID();
256 bool IsRange()
const override {
return false; }
257 size_t GetSize()
const override {
return m_pubkey.size(); }
258 std::string
ToString()
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
259 bool ToPrivateString(
const SigningProvider& arg, std::string& ret)
const override 262 if (!arg.
GetKey(m_pubkey.GetID(), key))
return false;
273 return arg.
GetKey(m_pubkey.GetID(), key);
284 class BIP32PubkeyProvider final :
public PubkeyProvider
294 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
295 ret.
nDepth = m_root_extkey.nDepth;
297 ret.
nChild = m_root_extkey.nChild;
306 if (!GetExtKey(arg, xprv))
return false;
307 for (
auto entry : m_path) {
310 last_hardened = xprv;
316 bool IsHardened()
const 318 if (m_derive == DeriveType::HARDENED)
return true;
319 for (
auto entry : m_path) {
320 if (entry >> 31)
return true;
326 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) {}
327 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
328 size_t GetSize()
const override {
return 33; }
333 CKeyID keyid = m_root_extkey.pubkey.GetID();
335 parent_info.
path = m_path;
339 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
340 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
348 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
349 if (m_derive == DeriveType::HARDENED)
return false;
351 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
352 final_extkey = parent_extkey;
353 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
355 }
else if (IsHardened()) {
358 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
359 parent_extkey = xprv.
Neuter();
360 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
361 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
362 final_extkey = xprv.
Neuter();
364 last_hardened_extkey = lh_xprv.
Neuter();
367 for (
auto entry : m_path) {
368 der = parent_extkey.
Derive(parent_extkey, entry);
371 final_extkey = parent_extkey;
372 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
373 assert(m_derive != DeriveType::HARDENED);
377 final_info_out = final_info_out_tmp;
378 key_out = final_extkey.
pubkey;
382 if (m_derive != DeriveType::HARDENED) {
383 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
386 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
388 }
else if (final_info_out.
path.size() > 0) {
389 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
395 std::string
ToString()
const override 400 if (m_derive == DeriveType::HARDENED) ret +=
'\'';
404 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const override 407 if (!GetExtKey(arg, key))
return false;
411 if (m_derive == DeriveType::HARDENED) out +=
'\'';
418 if (m_derive == DeriveType::HARDENED) {
423 int i = (int)m_path.size() - 1;
424 for (; i >= 0; --i) {
425 if (m_path.at(i) >> 31) {
437 for (; k <= i; ++k) {
439 origin.
path.push_back(m_path.at(k));
443 for (; k < (int)m_path.size(); ++k) {
444 end_path.push_back(m_path.at(k));
447 CKeyID id = m_root_extkey.pubkey.GetID();
448 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
453 if (cache !=
nullptr) {
459 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
469 assert(m_derive == DeriveType::UNHARDENED);
477 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
478 if (m_derive == DeriveType::UNHARDENED) extkey.
Derive(extkey, pos);
479 if (m_derive == DeriveType::HARDENED) extkey.
Derive(extkey, pos | 0x80000000UL);
489 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
491 const std::string m_name;
498 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
501 virtual std::string ToStringExtra()
const {
return ""; }
516 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
517 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))) {}
518 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)) {}
520 enum class StringType
529 for (
const auto& arg : m_subdescriptor_args) {
530 if (!arg->IsSolvable())
return false;
537 for (
const auto& pubkey : m_pubkey_args) {
538 if (pubkey->IsRange())
return true;
540 for (
const auto& arg : m_subdescriptor_args) {
541 if (arg->IsRange())
return true;
546 virtual bool ToStringSubScriptHelper(
const SigningProvider* arg, std::string& ret,
const StringType type,
const DescriptorCache* cache =
nullptr)
const 549 for (
const auto& scriptarg : m_subdescriptor_args) {
550 if (pos++) ret +=
",";
552 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
553 ret += std::move(tmp);
560 std::string extra = ToStringExtra();
561 size_t pos = extra.size() > 0 ? 1 : 0;
562 std::string ret = m_name +
"(" + extra;
563 for (
const auto& pubkey : m_pubkey_args) {
564 if (pos++) ret +=
",";
567 case StringType::NORMALIZED:
568 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
570 case StringType::PRIVATE:
571 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
573 case StringType::PUBLIC:
574 tmp = pubkey->ToString();
577 ret += std::move(tmp);
579 std::string subscript;
580 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
581 if (pos && subscript.size()) ret +=
',';
582 out = std::move(ret) + std::move(subscript) +
")";
589 ToStringHelper(
nullptr, ret, StringType::PUBLIC);
590 return AddChecksum(ret);
595 bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
596 out = AddChecksum(out);
602 bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
603 out = AddChecksum(out);
609 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
610 entries.reserve(m_pubkey_args.size());
613 for (
const auto& p : m_pubkey_args) {
614 entries.emplace_back();
615 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
617 std::vector<CScript> subscripts;
619 for (
const auto& subarg : m_subdescriptor_args) {
620 std::vector<CScript> outscripts;
621 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
622 assert(outscripts.size() == 1);
623 subscripts.emplace_back(std::move(outscripts[0]));
625 out =
Merge(std::move(out), std::move(subprovider));
627 std::vector<CPubKey> pubkeys;
628 pubkeys.reserve(entries.size());
629 for (
auto& entry : entries) {
630 pubkeys.push_back(entry.first);
631 out.
origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
634 output_scripts = MakeScripts(pubkeys,
MakeSpan(subscripts), out);
640 return ExpandHelper(pos, provider,
nullptr, output_scripts, out, write_cache);
650 for (
const auto& p : m_pubkey_args) {
652 if (!p->GetPrivKey(pos, provider, key))
continue;
655 for (
const auto& arg : m_subdescriptor_args) {
656 arg->ExpandPrivate(pos, provider, out);
660 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
664 class AddressDescriptor final :
public DescriptorImpl
668 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
671 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
672 bool IsSolvable() const final {
return false; }
674 std::optional<OutputType> GetOutputType()
const override 678 bool IsSingleType() const final {
return true; }
682 class RawDescriptor final :
public DescriptorImpl
686 std::string ToStringExtra()
const override {
return HexStr(m_script); }
689 RawDescriptor(
CScript script) : DescriptorImpl({},
"raw"), m_script(std::move(script)) {}
690 bool IsSolvable() const final {
return false; }
692 std::optional<OutputType> GetOutputType()
const override 698 bool IsSingleType() const final {
return true; }
702 class PKDescriptor final :
public DescriptorImpl
711 return Vector(std::move(script));
717 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
718 bool IsSingleType() const final {
return true; }
722 class PKHDescriptor final :
public DescriptorImpl
727 CKeyID id = keys[0].GetID();
728 out.
pubkeys.emplace(
id, keys[0]);
732 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
733 std::optional<OutputType> GetOutputType()
const override {
return OutputType::LEGACY; }
734 bool IsSingleType() const final {
return true; }
738 class WPKHDescriptor final :
public DescriptorImpl
743 CKeyID id = keys[0].GetID();
744 out.
pubkeys.emplace(
id, keys[0]);
748 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
749 std::optional<OutputType> GetOutputType()
const override {
return OutputType::BECH32; }
750 bool IsSingleType() const final {
return true; }
754 class ComboDescriptor final :
public DescriptorImpl
759 std::vector<CScript> ret;
760 CKeyID id = keys[0].GetID();
761 out.
pubkeys.emplace(
id, keys[0]);
764 if (keys[0].IsCompressed()) {
767 ret.emplace_back(p2wpkh);
773 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
774 bool IsSingleType() const final {
return false; }
778 class MultisigDescriptor final :
public DescriptorImpl
780 const int m_threshold;
783 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
786 std::vector<CPubKey> sorted_keys(keys);
787 std::sort(sorted_keys.begin(), sorted_keys.end());
793 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) {}
794 bool IsSingleType() const final {
return true; }
798 class SHDescriptor final :
public DescriptorImpl
808 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
810 std::optional<OutputType> GetOutputType()
const override 812 assert(m_subdescriptor_args.size() == 1);
816 bool IsSingleType() const final {
return true; }
820 class WSHDescriptor final :
public DescriptorImpl
830 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
831 std::optional<OutputType> GetOutputType()
const override {
return OutputType::BECH32; }
832 bool IsSingleType() const final {
return true; }
836 class TRDescriptor final :
public DescriptorImpl
838 std::vector<int> m_depths;
844 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
850 if (!xpk.IsFullyValid())
return {};
856 bool ToStringSubScriptHelper(
const SigningProvider* arg, std::string& ret,
const StringType type,
const DescriptorCache* cache =
nullptr)
const override 858 if (m_depths.empty())
return true;
859 std::vector<bool> path;
860 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
862 while ((
int)path.size() <= m_depths[pos]) {
863 if (path.size()) ret +=
'{';
864 path.push_back(
false);
867 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
868 ret += std::move(tmp);
869 while (!path.empty() && path.back()) {
870 if (path.size() > 1) ret +=
'}';
873 if (!path.empty()) path.back() =
true;
878 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
879 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
881 assert(m_subdescriptor_args.size() == m_depths.size());
884 bool IsSingleType() const final {
return true; }
900 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath& out, std::string&
error)
902 for (
size_t i = 1; i < split.size(); ++i) {
904 bool hardened =
false;
905 if (elem.
size() > 0 && (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
913 }
else if (p > 0x7FFFFFFFUL) {
917 out.push_back(p | (((uint32_t)hardened) << 31));
927 bool permit_uncompressed =
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH;
928 auto split =
Split(sp,
'/');
929 std::string str(split[0].begin(), split[0].end());
930 if (str.size() == 0) {
931 error =
"No key provided";
934 if (split.size() == 1) {
936 std::vector<unsigned char> data =
ParseHex(str);
938 if (pubkey.IsFullyValid()) {
939 if (permit_uncompressed || pubkey.IsCompressed()) {
940 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false);
942 error =
"Uncompressed keys are not allowed";
945 }
else if (data.size() == 32 &&
ctx == ParseScriptContext::P2TR) {
946 unsigned char fullkey[33] = {0x02};
947 std::copy(data.begin(), data.end(), fullkey + 1);
948 pubkey.Set(std::begin(fullkey), std::end(fullkey));
949 if (pubkey.IsFullyValid()) {
950 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true);
961 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
ctx == ParseScriptContext::P2TR);
963 error =
"Uncompressed keys are not allowed";
976 if (split.back() ==
MakeSpan(
"*").first(1)) {
978 type = DeriveType::UNHARDENED;
979 }
else if (split.back() ==
MakeSpan(
"*'").first(2) || split.back() ==
MakeSpan(
"*h").first(2)) {
981 type = DeriveType::HARDENED;
983 if (!ParseKeyPath(split, path,
error))
return nullptr;
985 extpubkey = extkey.
Neuter();
988 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
996 auto origin_split =
Split(sp,
']');
997 if (origin_split.size() > 2) {
998 error =
"Multiple ']' characters found for a single pubkey";
1001 if (origin_split.size() == 1)
return ParsePubkeyInner(key_exp_index, origin_split[0],
ctx, out,
error);
1002 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1003 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1004 origin_split[0].empty() ?
']' : origin_split[0][0]);
1007 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1008 if (slash_split[0].size() != 8) {
1009 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1012 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1013 if (!
IsHex(fpr_hex)) {
1017 auto fpr_bytes =
ParseHex(fpr_hex);
1019 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1020 assert(fpr_bytes.size() == 4);
1021 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1022 if (!ParseKeyPath(slash_split, info.
path,
error))
return nullptr;
1023 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1],
ctx, out,
error);
1024 if (!provider)
return nullptr;
1025 return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
1033 auto expr =
Expr(sp);
1034 bool sorted_multi =
false;
1035 if (
Func(
"pk", expr)) {
1036 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1037 if (!pubkey)
return nullptr;
1039 return std::make_unique<PKDescriptor>(std::move(pubkey),
ctx == ParseScriptContext::P2TR);
1041 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1042 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1043 if (!pubkey)
return nullptr;
1045 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1046 }
else if (
Func(
"pkh", expr)) {
1047 error =
"Can only have pkh at top level, in sh(), or in wsh()";
1050 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1051 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1052 if (!pubkey)
return nullptr;
1054 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1055 }
else if (
Func(
"combo", expr)) {
1056 error =
"Can only have combo() at top level";
1059 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) && ((sorted_multi =
Func(
"sortedmulti", expr)) ||
Func(
"multi", expr))) {
1060 auto threshold =
Expr(expr);
1062 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1063 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1064 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1067 size_t script_size = 0;
1068 while (expr.size()) {
1069 if (!
Const(
",", expr)) {
1073 auto arg =
Expr(expr);
1074 auto pk = ParsePubkey(key_exp_index, arg,
ctx, out,
error);
1075 if (!pk)
return nullptr;
1076 script_size += pk->GetSize() + 1;
1077 providers.emplace_back(std::move(pk));
1083 }
else if (thres < 1) {
1084 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1086 }
else if (thres > providers.size()) {
1087 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1090 if (
ctx == ParseScriptContext::TOP) {
1091 if (providers.size() > 3) {
1092 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1096 if (
ctx == ParseScriptContext::P2SH) {
1103 return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sorted_multi);
1104 }
else if (
Func(
"sortedmulti", expr) ||
Func(
"multi", expr)) {
1105 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1108 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1109 auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out,
error);
1110 if (!pubkey)
return nullptr;
1112 return std::make_unique<WPKHDescriptor>(std::move(pubkey));
1113 }
else if (
Func(
"wpkh", expr)) {
1114 error =
"Can only have wpkh() at top level or inside sh()";
1117 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1118 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out,
error);
1119 if (!desc || expr.size())
return nullptr;
1120 return std::make_unique<SHDescriptor>(std::move(desc));
1121 }
else if (
Func(
"sh", expr)) {
1122 error =
"Can only have sh() at top level";
1125 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1126 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out,
error);
1127 if (!desc || expr.size())
return nullptr;
1128 return std::make_unique<WSHDescriptor>(std::move(desc));
1129 }
else if (
Func(
"wsh", expr)) {
1130 error =
"Can only have wsh() at top level or inside sh()";
1133 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1136 error =
"Address is not valid";
1139 return std::make_unique<AddressDescriptor>(std::move(dest));
1140 }
else if (
Func(
"addr", expr)) {
1141 error =
"Can only have addr() at top level";
1144 if (
ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1145 auto arg =
Expr(expr);
1146 auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out,
error);
1147 if (!internal_key)
return nullptr;
1149 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1150 std::vector<int> depths;
1152 if (!
Const(
",", expr)) {
1159 std::vector<bool> branches;
1164 while (
Const(
"{", expr)) {
1165 branches.push_back(
false);
1172 auto sarg =
Expr(expr);
1173 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR, out,
error));
1174 if (!subscripts.back())
return nullptr;
1175 depths.push_back(branches.size());
1177 while (branches.size() && branches.back()) {
1178 if (!
Const(
"}", expr)) {
1182 branches.pop_back();
1185 if (branches.size() && !branches.back()) {
1186 if (!
Const(
",", expr)) {
1190 branches.back() =
true;
1192 }
while (branches.size());
1200 return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
1201 }
else if (
Func(
"tr", expr)) {
1202 error =
"Can only have tr at top level";
1205 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1206 std::string str(expr.begin(), expr.end());
1208 error =
"Raw script is not hex";
1212 return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
1213 }
else if (
Func(
"raw", expr)) {
1214 error =
"Can only have raw() at top level";
1217 if (
ctx == ParseScriptContext::P2SH) {
1218 error =
"A function is needed within P2SH";
1220 }
else if (
ctx == ParseScriptContext::P2WSH) {
1221 error =
"A function is needed within P2WSH";
1224 error =
strprintf(
"%s is not a valid descriptor function", std::string(expr.begin(), expr.end()));
1230 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1233 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1235 return key_provider;
1241 std::copy(xkey.
begin(), xkey.
end(), full_key + 1);
1243 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1246 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1251 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1254 return key_provider;
1259 if (
ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] ==
OP_CHECKSIG) {
1261 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key,
ctx, provider));
1264 std::vector<std::vector<unsigned char>> data;
1267 if (txntype ==
TxoutType::PUBKEY && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1269 if (pubkey.IsValid()) {
1270 return std::make_unique<PKDescriptor>(InferPubkey(pubkey,
ctx, provider));
1273 if (txntype ==
TxoutType::PUBKEYHASH && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1277 if (provider.
GetPubKey(keyid, pubkey)) {
1278 return std::make_unique<PKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1285 if (provider.
GetPubKey(keyid, pubkey)) {
1286 return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1289 if (txntype ==
TxoutType::MULTISIG && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1290 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1291 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1293 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1295 return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1301 if (provider.
GetCScript(scriptid, subscript)) {
1302 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1303 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1310 if (provider.
GetCScript(scriptid, subscript)) {
1311 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1312 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1318 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1327 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1328 std::vector<int> depths;
1329 for (
const auto& [depth, script, leaf_ver] : *tree) {
1330 std::unique_ptr<DescriptorImpl> subdesc;
1332 subdesc = InferScript(script, ParseScriptContext::P2TR, provider);
1338 subscripts.push_back(std::move(subdesc));
1339 depths.push_back(depth);
1343 auto key = InferXOnlyPubkey(tap.internal_key, ParseScriptContext::P2TR, provider);
1344 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
1353 return std::make_unique<AddressDescriptor>(std::move(dest));
1357 return std::make_unique<RawDescriptor>(script);
1368 auto check_split =
Split(sp,
'#');
1369 if (check_split.size() > 2) {
1370 error =
"Multiple '#' symbols";
1373 if (check_split.size() == 1 && require_checksum){
1374 error =
"Missing checksum";
1377 if (check_split.size() == 2) {
1378 if (check_split[1].size() != 8) {
1379 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
1383 auto checksum = DescriptorChecksum(check_split[0]);
1384 if (checksum.empty()) {
1385 error =
"Invalid characters in payload";
1388 if (check_split.size() == 2) {
1389 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1390 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1394 if (out_checksum) *out_checksum = std::move(checksum);
1395 sp = check_split[0];
1403 uint32_t key_exp_index = 0;
1404 auto ret =
ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out,
error);
1405 if (sp.
size() == 0 && ret)
return std::unique_ptr<Descriptor>(std::move(ret));
1420 return InferScript(script, ParseScriptContext::TOP, provider);
1431 xpubs[der_index] = xpub;
1451 const auto& der_it = key_exp_it->second.find(der_index);
1452 if (der_it == key_exp_it->second.end())
return false;
1453 xpub = der_it->second;
1471 if (xpub != parent_xpub_pair.second) {
1472 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
1480 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
1483 if (xpub != derived_xpub_pair.second) {
1484 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
1488 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1489 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1495 if (xpub != lh_xpub_pair.second) {
1496 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
static const int MAX_PUBKEYS_PER_MULTISIG
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.
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
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
CExtKey DecodeExtKey(const std::string &str)
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
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.
std::vector< unsigned char > ParseHex(const char *psz)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
constexpr std::size_t size() const noexcept
unsigned char vchFingerprint[4]
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...
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
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::vector< Span< const char > > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
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 unsigned int MAX_SCRIPT_ELEMENT_SIZE
CExtPubKey DecodeExtPubKey(const std::string &str)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
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.
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.
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.
static constexpr unsigned int COMPRESSED_SIZE
const unsigned char * begin() const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
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.
bool IsHex(const std::string &str)
std::map< CKeyID, CPubKey > pubkeys
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
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
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
virtual bool GetKey(const CKeyID &address, CKey &key) const
bool IsSolvable(const SigningProvider &provider, const CScript &script)
CRIPEMD160 & Write(const unsigned char *data, size_t len)
TaprootSpendData GetSpendData() const
Compute spending data (after Finalize()).
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.
constexpr C * begin() const noexcept
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.
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.
std::map< XOnlyPubKey, TaprootSpendData > tr_spenddata
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)
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
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::vector< unsigned char > ToByteVector(const T &in)
Span< A > constexpr MakeSpan(A(&a)[N])
MakeSpan for arrays: