Changeset View
Changeset View
Standalone View
Standalone View
src/script/descriptor.cpp
Show First 20 Lines • Show All 388 Lines • ▼ Show 20 Lines | bool ToPrivateString(const SigningProvider &arg, | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
}; | }; | ||||
/** Base class for all Descriptor implementations. */ | /** Base class for all Descriptor implementations. */ | ||||
class DescriptorImpl : public Descriptor { | class DescriptorImpl : public Descriptor { | ||||
//! Public key arguments for this descriptor (size 1 for PK, PKH; any size | //! Public key arguments for this descriptor (size 1 for PK, PKH; any size | ||||
//! of Multisig). | //! for Multisig). | ||||
const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args; | const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args; | ||||
//! The sub-descriptor argument (nullptr for everything but SH). | //! The sub-descriptor argument (nullptr for everything but SH). | ||||
const std::unique_ptr<DescriptorImpl> m_script_arg; | //! In doc/descriptors.m this is referred to as SCRIPT expressions | ||||
//! sh(SCRIPT), and distinct from KEY expressions and ADDR expressions. | |||||
const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg; | |||||
//! The string name of the descriptor function. | //! The string name of the descriptor function. | ||||
const std::string m_name; | const std::string m_name; | ||||
protected: | protected: | ||||
//! Return a serialization of anything except pubkey and script arguments, | //! Return a serialization of anything except pubkey and script arguments, | ||||
//! to be prepended to those. | //! to be prepended to those. | ||||
virtual std::string ToStringExtra() const { return ""; } | virtual std::string ToStringExtra() const { return ""; } | ||||
/** | /** | ||||
* A helper function to construct the scripts for this descriptor. | * A helper function to construct the scripts for this descriptor. | ||||
* | * | ||||
* This function is invoked once for every CScript produced by evaluating | * This function is invoked once for every CScript produced by evaluating | ||||
* m_script_arg, or just once in case m_script_arg is nullptr. | * m_subdescriptor_arg, or just once in case m_subdescriptor_arg is | ||||
nullptr. | |||||
* @param pubkeys The evaluations of the m_pubkey_args field. | * @param pubkeys The evaluations of the m_pubkey_args field. | ||||
* @param script The evaluation of m_script_arg (or nullptr when | * @param script The evaluation of m_subdescriptor_arg (or nullptr when | ||||
m_script_arg is nullptr). | m_subdescriptor_arg is nullptr). | ||||
* @param out A FlatSigningProvider to put scripts or public keys in that | * @param out A FlatSigningProvider to put scripts or public keys in that | ||||
are necessary to the solver. | are necessary to the solver. | ||||
* The script arguments to this function are automatically | * The script arguments to this function are automatically | ||||
added, as is the origin info of the provided pubkeys. | added, as is the origin info of the provided pubkeys. | ||||
* @return A vector with scriptPubKeys for this descriptor. | * @return A vector with scriptPubKeys for this descriptor. | ||||
*/ | */ | ||||
virtual std::vector<CScript> | virtual std::vector<CScript> | ||||
MakeScripts(const std::vector<CPubKey> &pubkeys, const CScript *script, | MakeScripts(const std::vector<CPubKey> &pubkeys, const CScript *script, | ||||
FlatSigningProvider &out) const = 0; | FlatSigningProvider &out) const = 0; | ||||
public: | public: | ||||
DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, | DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, | ||||
std::unique_ptr<DescriptorImpl> script, | std::unique_ptr<DescriptorImpl> script, | ||||
const std::string &name) | const std::string &name) | ||||
: m_pubkey_args(std::move(pubkeys)), m_script_arg(std::move(script)), | : m_pubkey_args(std::move(pubkeys)), | ||||
m_name(name) {} | m_subdescriptor_arg(std::move(script)), m_name(name) {} | ||||
bool IsSolvable() const override { | bool IsSolvable() const override { | ||||
if (m_script_arg) { | if (m_subdescriptor_arg) { | ||||
if (!m_script_arg->IsSolvable()) { | if (!m_subdescriptor_arg->IsSolvable()) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool IsRange() const final { | bool IsRange() const final { | ||||
for (const auto &pubkey : m_pubkey_args) { | for (const auto &pubkey : m_pubkey_args) { | ||||
if (pubkey->IsRange()) { | if (pubkey->IsRange()) { | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
if (m_script_arg) { | if (m_subdescriptor_arg) { | ||||
if (m_script_arg->IsRange()) { | if (m_subdescriptor_arg->IsRange()) { | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
bool ToStringHelper(const SigningProvider *arg, std::string &out, | bool ToStringHelper(const SigningProvider *arg, std::string &out, | ||||
bool priv) const { | bool priv) const { | ||||
Show All 9 Lines | bool ToStringHelper(const SigningProvider *arg, std::string &out, | ||||
if (!pubkey->ToPrivateString(*arg, tmp)) { | if (!pubkey->ToPrivateString(*arg, tmp)) { | ||||
return false; | return false; | ||||
} | } | ||||
} else { | } else { | ||||
tmp = pubkey->ToString(); | tmp = pubkey->ToString(); | ||||
} | } | ||||
ret += std::move(tmp); | ret += std::move(tmp); | ||||
} | } | ||||
if (m_script_arg) { | if (m_subdescriptor_arg) { | ||||
if (pos++) { | if (pos++) { | ||||
ret += ","; | ret += ","; | ||||
} | } | ||||
std::string tmp; | std::string tmp; | ||||
if (!m_script_arg->ToStringHelper(arg, tmp, priv)) { | if (!m_subdescriptor_arg->ToStringHelper(arg, tmp, priv)) { | ||||
return false; | return false; | ||||
} | } | ||||
ret += std::move(tmp); | ret += std::move(tmp); | ||||
} | } | ||||
out = std::move(ret) + ")"; | out = std::move(ret) + ")"; | ||||
return true; | return true; | ||||
} | } | ||||
Show All 17 Lines | bool ExpandHelper(int pos, const SigningProvider &arg, | ||||
std::vector<uint8_t> *cache_write) const { | std::vector<uint8_t> *cache_write) const { | ||||
std::vector<std::pair<CPubKey, KeyOriginInfo>> entries; | std::vector<std::pair<CPubKey, KeyOriginInfo>> entries; | ||||
entries.reserve(m_pubkey_args.size()); | entries.reserve(m_pubkey_args.size()); | ||||
// Construct temporary data in `entries` and `subscripts`, to avoid | // Construct temporary data in `entries` and `subscripts`, to avoid | ||||
// producing output in case of failure. | // producing output in case of failure. | ||||
for (const auto &p : m_pubkey_args) { | for (const auto &p : m_pubkey_args) { | ||||
entries.emplace_back(); | entries.emplace_back(); | ||||
// If we have a cache, we don't need GetPubKey to compute the public | |||||
// key. Pass in nullptr to signify only origin info is desired. | |||||
if (!p->GetPubKey(pos, arg, | if (!p->GetPubKey(pos, arg, | ||||
cache_read ? nullptr : &entries.back().first, | cache_read ? nullptr : &entries.back().first, | ||||
entries.back().second)) { | entries.back().second)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (cache_read) { | if (cache_read) { | ||||
// Cached expanded public key exists, use it. | // Cached expanded public key exists, use it. | ||||
if (cache_read->size() == 0) { | if (cache_read->size() == 0) { | ||||
Show All 14 Lines | bool ExpandHelper(int pos, const SigningProvider &arg, | ||||
} | } | ||||
if (cache_write) { | if (cache_write) { | ||||
cache_write->insert(cache_write->end(), | cache_write->insert(cache_write->end(), | ||||
entries.back().first.begin(), | entries.back().first.begin(), | ||||
entries.back().first.end()); | entries.back().first.end()); | ||||
} | } | ||||
} | } | ||||
std::vector<CScript> subscripts; | std::vector<CScript> subscripts; | ||||
if (m_script_arg) { | if (m_subdescriptor_arg) { | ||||
FlatSigningProvider subprovider; | FlatSigningProvider subprovider; | ||||
if (!m_script_arg->ExpandHelper(pos, arg, cache_read, subscripts, | if (!m_subdescriptor_arg->ExpandHelper(pos, arg, cache_read, | ||||
subprovider, cache_write)) { | subscripts, subprovider, | ||||
cache_write)) { | |||||
return false; | return false; | ||||
} | } | ||||
out = Merge(out, subprovider); | out = Merge(out, subprovider); | ||||
} | } | ||||
std::vector<CPubKey> pubkeys; | std::vector<CPubKey> pubkeys; | ||||
pubkeys.reserve(entries.size()); | pubkeys.reserve(entries.size()); | ||||
for (auto &entry : entries) { | for (auto &entry : entries) { | ||||
pubkeys.push_back(entry.first); | pubkeys.push_back(entry.first); | ||||
out.origins.emplace( | out.origins.emplace( | ||||
entry.first.GetID(), | entry.first.GetID(), | ||||
std::make_pair<CPubKey, KeyOriginInfo>( | std::make_pair<CPubKey, KeyOriginInfo>( | ||||
CPubKey(entry.first), std::move(entry.second))); | CPubKey(entry.first), std::move(entry.second))); | ||||
} | } | ||||
if (m_script_arg) { | if (m_subdescriptor_arg) { | ||||
for (const auto &subscript : subscripts) { | for (const auto &subscript : subscripts) { | ||||
out.scripts.emplace(CScriptID(subscript), subscript); | out.scripts.emplace(CScriptID(subscript), subscript); | ||||
std::vector<CScript> addscripts = | std::vector<CScript> addscripts = | ||||
MakeScripts(pubkeys, &subscript, out); | MakeScripts(pubkeys, &subscript, out); | ||||
for (auto &addscript : addscripts) { | for (auto &addscript : addscripts) { | ||||
output_scripts.push_back(std::move(addscript)); | output_scripts.push_back(std::move(addscript)); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 563 Lines • Show Last 20 Lines |