84uint64_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];
143std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
149typedef std::vector<uint32_t> KeyPath;
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;
190class 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);
241class 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);
277enum class DeriveType {
284class 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; }
664class 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; }
682class 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; }
702class 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; }
722class 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; }
738class 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; }
754class 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; }
778class 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; }
798class 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; }
820class 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; }
836class 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; }
891enum class ParseScriptContext {
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";
975 DeriveType type = DeriveType::NO;
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()));
1228std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext,
const SigningProvider& provider)
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));
1248 return key_provider;
1251std::unique_ptr<DescriptorImpl> InferScript(
const CScript& script, ParseScriptContext
ctx,
const SigningProvider& provider)
1253 if (
ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] ==
OP_CHECKSIG) {
1255 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key,
ctx, provider));
1258 std::vector<std::vector<unsigned char>> data;
1261 if (txntype ==
TxoutType::PUBKEY && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1264 return std::make_unique<PKDescriptor>(InferPubkey(pubkey,
ctx, provider));
1267 if (txntype ==
TxoutType::PUBKEYHASH && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1271 if (provider.
GetPubKey(keyid, pubkey)) {
1272 return std::make_unique<PKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1279 if (provider.
GetPubKey(keyid, pubkey)) {
1280 return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1283 if (txntype ==
TxoutType::MULTISIG && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1284 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1285 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1287 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1289 return std::make_unique<MultisigDescriptor>((
int)data[0][0], std::move(providers));
1295 if (provider.
GetCScript(scriptid, subscript)) {
1296 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1297 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1304 if (provider.
GetCScript(scriptid, subscript)) {
1305 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1306 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1312 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1321 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1322 std::vector<int> depths;
1323 for (
const auto& [depth, script, leaf_ver] : *tree) {
1324 std::unique_ptr<DescriptorImpl> subdesc;
1326 subdesc = InferScript(script, ParseScriptContext::P2TR, provider);
1332 subscripts.push_back(std::move(subdesc));
1333 depths.push_back(depth);
1337 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
1338 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
1347 return std::make_unique<AddressDescriptor>(std::move(dest));
1351 return std::make_unique<RawDescriptor>(script);
1362 auto check_split =
Split(sp,
'#');
1363 if (check_split.size() > 2) {
1364 error =
"Multiple '#' symbols";
1367 if (check_split.size() == 1 && require_checksum){
1368 error =
"Missing checksum";
1371 if (check_split.size() == 2) {
1372 if (check_split[1].size() != 8) {
1373 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
1377 auto checksum = DescriptorChecksum(check_split[0]);
1378 if (checksum.empty()) {
1379 error =
"Invalid characters in payload";
1382 if (check_split.size() == 2) {
1383 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1384 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1388 if (out_checksum) *out_checksum = std::move(checksum);
1389 sp = check_split[0];
1397 uint32_t key_exp_index = 0;
1398 auto ret =
ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out,
error);
1399 if (sp.
size() == 0 && ret)
return std::unique_ptr<Descriptor>(std::move(ret));
1414 return InferScript(script, ParseScriptContext::TOP, provider);
1425 xpubs[der_index] = xpub;
1445 const auto& der_it = key_exp_it->second.find(der_index);
1446 if (der_it == key_exp_it->second.end())
return false;
1447 xpub = der_it->second;
1465 if (xpub != parent_xpub_pair.second) {
1466 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
1474 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
1477 if (xpub != derived_xpub_pair.second) {
1478 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
1482 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1483 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1489 if (xpub != lh_xpub_pair.second) {
1490 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
An encapsulated private key.
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CPubKey GetPubKey() const
Compute the public key from a private key.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
static constexpr unsigned int COMPRESSED_SIZE
A hasher class for RIPEMD-160.
CRIPEMD160 & Write(const unsigned char *data, size_t len)
void Finalize(unsigned char hash[OUTPUT_SIZE])
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization (see script.h)
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened xpub.
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
constexpr C * begin() const noexcept
constexpr C * end() const noexcept
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
TaprootSpendData GetSpendData() const
Compute spending data (after Finalize()).
TaprootBuilder & Add(int depth, const CScript &script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * end() const
const unsigned char * begin() const
CScript ParseScript(const std::string &s)
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
CExtKey DecodeExtKey(const std::string &str)
std::vector< Span< const char > > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
@ TOP
Top-level scriptPubKey.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static const int MAX_PUBKEYS_PER_MULTISIG
std::vector< unsigned char > ToByteVector(const T &in)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
const SigningProvider & DUMMY_SIGNING_PROVIDER
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
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.
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< unsigned char > ParseHex(const char *psz)
bool ParseUInt32(const std::string &str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
bool IsHex(const std::string &str)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
unsigned char vchFingerprint[4]
CExtPubKey Neuter() const
bool Derive(CExtKey &out, unsigned int nChild) const
bool Derive(CExtPubKey &out, unsigned int nChild) const
Interface for parsed descriptor objects.
virtual std::string ToString() const =0
Convert the descriptor back to a string, undoing parsing.
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual std::optional< OutputType > GetOutputType() const =0
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.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
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.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
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.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< XOnlyPubKey, TaprootSpendData > tr_spenddata
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
std::vector< uint32_t > path
XOnlyPubKey internal_key
The BIP341 internal key.
bool error(const char *fmt, const Args &... args)
static secp256k1_context * ctx
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.