Changeset View
Changeset View
Standalone View
Standalone View
src/script/descriptor.cpp
Show First 20 Lines • Show All 687 Lines • ▼ Show 20 Lines | |||||
public: | public: | ||||
ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) | ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) | ||||
: DescriptorImpl(Vector(std::move(prov)), {}, "combo") {} | : DescriptorImpl(Vector(std::move(prov)), {}, "combo") {} | ||||
}; | }; | ||||
/** A parsed multi(...) descriptor. */ | /** A parsed multi(...) descriptor. */ | ||||
class MultisigDescriptor final : public DescriptorImpl { | class MultisigDescriptor final : public DescriptorImpl { | ||||
const int m_threshold; | const int m_threshold; | ||||
const bool m_sorted; | |||||
protected: | protected: | ||||
std::string ToStringExtra() const override { | std::string ToStringExtra() const override { | ||||
return strprintf("%i", m_threshold); | return strprintf("%i", m_threshold); | ||||
} | } | ||||
std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys, | std::vector<CScript> MakeScripts(const std::vector<CPubKey> &keys, | ||||
const CScript *, | const CScript *, | ||||
FlatSigningProvider &) const override { | FlatSigningProvider &) const override { | ||||
if (m_sorted) { | |||||
std::vector<CPubKey> sorted_keys(keys); | |||||
std::sort(sorted_keys.begin(), sorted_keys.end()); | |||||
return Vector(GetScriptForMultisig(m_threshold, sorted_keys)); | |||||
} | |||||
return Vector(GetScriptForMultisig(m_threshold, keys)); | return Vector(GetScriptForMultisig(m_threshold, keys)); | ||||
} | } | ||||
public: | public: | ||||
MultisigDescriptor(int threshold, | MultisigDescriptor(int threshold, | ||||
std::vector<std::unique_ptr<PubkeyProvider>> providers) | std::vector<std::unique_ptr<PubkeyProvider>> providers, | ||||
: DescriptorImpl(std::move(providers), {}, "multi"), | bool sorted = false) | ||||
m_threshold(threshold) {} | : DescriptorImpl(std::move(providers), {}, | ||||
sorted ? "sortedmulti" : "multi"), | |||||
m_threshold(threshold), m_sorted(sorted) {} | |||||
}; | }; | ||||
/** A parsed sh(...) descriptor. */ | /** A parsed sh(...) descriptor. */ | ||||
class SHDescriptor final : public DescriptorImpl { | class SHDescriptor final : public DescriptorImpl { | ||||
protected: | protected: | ||||
std::vector<CScript> MakeScripts(const std::vector<CPubKey> &, | std::vector<CScript> MakeScripts(const std::vector<CPubKey> &, | ||||
const CScript *script, | const CScript *script, | ||||
FlatSigningProvider &) const override { | FlatSigningProvider &) const override { | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
/** Parse a script in a particular context. */ | /** Parse a script in a particular context. */ | ||||
std::unique_ptr<DescriptorImpl> ParseScript(Span<const char> &sp, | std::unique_ptr<DescriptorImpl> ParseScript(Span<const char> &sp, | ||||
ParseScriptContext ctx, | ParseScriptContext ctx, | ||||
FlatSigningProvider &out, | FlatSigningProvider &out, | ||||
std::string &error) { | std::string &error) { | ||||
using namespace spanparsing; | using namespace spanparsing; | ||||
auto expr = Expr(sp); | auto expr = Expr(sp); | ||||
bool sorted_multi = false; | |||||
if (Func("pk", expr)) { | if (Func("pk", expr)) { | ||||
auto pubkey = ParsePubkey(expr, out, error); | auto pubkey = ParsePubkey(expr, out, error); | ||||
if (!pubkey) { | if (!pubkey) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return std::make_unique<PKDescriptor>(std::move(pubkey)); | return std::make_unique<PKDescriptor>(std::move(pubkey)); | ||||
} | } | ||||
if (Func("pkh", expr)) { | if (Func("pkh", expr)) { | ||||
auto pubkey = ParsePubkey(expr, out, error); | auto pubkey = ParsePubkey(expr, out, error); | ||||
if (!pubkey) { | if (!pubkey) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return std::make_unique<PKHDescriptor>(std::move(pubkey)); | return std::make_unique<PKHDescriptor>(std::move(pubkey)); | ||||
} | } | ||||
if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { | if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { | ||||
auto pubkey = ParsePubkey(expr, out, error); | auto pubkey = ParsePubkey(expr, out, error); | ||||
if (!pubkey) { | if (!pubkey) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return std::make_unique<ComboDescriptor>(std::move(pubkey)); | return std::make_unique<ComboDescriptor>(std::move(pubkey)); | ||||
} else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) { | } else if (ctx != ParseScriptContext::TOP && Func("combo", expr)) { | ||||
error = "Cannot have combo in non-top level"; | error = "Cannot have combo in non-top level"; | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
if (Func("multi", expr)) { | if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) { | ||||
auto threshold = Expr(expr); | auto threshold = Expr(expr); | ||||
uint32_t thres; | uint32_t thres; | ||||
std::vector<std::unique_ptr<PubkeyProvider>> providers; | std::vector<std::unique_ptr<PubkeyProvider>> providers; | ||||
if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), | if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), | ||||
&thres)) { | &thres)) { | ||||
error = strprintf( | error = strprintf( | ||||
"Multi threshold '%s' is not valid", | "Multi threshold '%s' is not valid", | ||||
std::string(threshold.begin(), threshold.end()).c_str()); | std::string(threshold.begin(), threshold.end()).c_str()); | ||||
Show All 40 Lines | if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) { | ||||
if (ctx == ParseScriptContext::P2SH) { | if (ctx == ParseScriptContext::P2SH) { | ||||
if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) { | if (script_size + 3 > MAX_SCRIPT_ELEMENT_SIZE) { | ||||
error = strprintf("P2SH script is too large, %d bytes is " | error = strprintf("P2SH script is too large, %d bytes is " | ||||
"larger than %d bytes", | "larger than %d bytes", | ||||
script_size + 3, MAX_SCRIPT_ELEMENT_SIZE); | script_size + 3, MAX_SCRIPT_ELEMENT_SIZE); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
return std::make_unique<MultisigDescriptor>(thres, | return std::make_unique<MultisigDescriptor>(thres, std::move(providers), | ||||
std::move(providers)); | sorted_multi); | ||||
} | } | ||||
if (ctx == ParseScriptContext::TOP && Func("sh", expr)) { | if (ctx == ParseScriptContext::TOP && Func("sh", expr)) { | ||||
auto desc = ParseScript(expr, ParseScriptContext::P2SH, out, error); | auto desc = ParseScript(expr, ParseScriptContext::P2SH, out, error); | ||||
if (!desc || expr.size()) { | if (!desc || expr.size()) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return std::make_unique<SHDescriptor>(std::move(desc)); | return std::make_unique<SHDescriptor>(std::move(desc)); | ||||
} else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) { | } else if (ctx != ParseScriptContext::TOP && Func("sh", expr)) { | ||||
▲ Show 20 Lines • Show All 173 Lines • Show Last 20 Lines |