Pass in DescriptorCache to ToNormalizedString
Use the descriptor xpub cache in ToNormalizedString so that the wallet does not need to be unlocked in order to get the normalized descriptor.
This commit is contained in:
1 parent
7a26ff10c2
commit
3280704886
3 files changed
+36
-26
No files matched your search
+34
-24
@@ -181,7 +181,7 @@ public:
|
|||||||
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
|
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
|
||||||
|
|
||||||
/** Get the descriptor string form with the xpub at the last hardened derivation */
|
/** Get the descriptor string form with the xpub at the last hardened derivation */
|
||||||
virtual bool ToNormalizedString(const SigningProvider& arg, std::string& out) const = 0;
|
virtual bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache = nullptr) const = 0;
|
||||||
|
|
||||||
/** Derive a private key, if private data is available in arg. */
|
/** Derive a private key, if private data is available in arg. */
|
||||||
virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
|
virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
|
||||||
@@ -216,10 +216,10 @@ public:
|
|||||||
ret = "[" + OriginString() + "]" + std::move(sub);
|
ret = "[" + OriginString() + "]" + std::move(sub);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ToNormalizedString(const SigningProvider& arg, std::string& ret) const override
|
bool ToNormalizedString(const SigningProvider& arg, std::string& ret, const DescriptorCache* cache) const override
|
||||||
{
|
{
|
||||||
std::string sub;
|
std::string sub;
|
||||||
if (!m_provider->ToNormalizedString(arg, sub)) return false;
|
if (!m_provider->ToNormalizedString(arg, sub, cache)) return false;
|
||||||
// If m_provider is a BIP32PubkeyProvider, we may get a string formatted like a OriginPubkeyProvider
|
// If m_provider is a BIP32PubkeyProvider, we may get a string formatted like a OriginPubkeyProvider
|
||||||
// In that case, we need to strip out the leading square bracket and fingerprint from the substring,
|
// In that case, we need to strip out the leading square bracket and fingerprint from the substring,
|
||||||
// and append that to our own origin string.
|
// and append that to our own origin string.
|
||||||
@@ -263,7 +263,7 @@ public:
|
|||||||
ret = EncodeSecret(key);
|
ret = EncodeSecret(key);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ToNormalizedString(const SigningProvider& arg, std::string& ret) const override
|
bool ToNormalizedString(const SigningProvider& arg, std::string& ret, const DescriptorCache* cache) const override
|
||||||
{
|
{
|
||||||
ret = ToString();
|
ret = ToString();
|
||||||
return true;
|
return true;
|
||||||
@@ -412,7 +412,7 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ToNormalizedString(const SigningProvider& arg, std::string& out) const override
|
bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override
|
||||||
{
|
{
|
||||||
// For hardened derivation type, just return the typical string, nothing to normalize
|
// For hardened derivation type, just return the typical string, nothing to normalize
|
||||||
if (m_derive == DeriveType::HARDENED) {
|
if (m_derive == DeriveType::HARDENED) {
|
||||||
@@ -431,29 +431,39 @@ public:
|
|||||||
out = ToString();
|
out = ToString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Derive the xpub at the last hardened step
|
// Get the path to the last hardened stup
|
||||||
CExtKey xprv;
|
|
||||||
if (!GetExtKey(arg, xprv)) return false;
|
|
||||||
KeyOriginInfo origin;
|
KeyOriginInfo origin;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (; k <= i; ++k) {
|
for (; k <= i; ++k) {
|
||||||
// Derive
|
|
||||||
xprv.Derive(xprv, m_path.at(k));
|
|
||||||
// Add to the path
|
// Add to the path
|
||||||
origin.path.push_back(m_path.at(k));
|
origin.path.push_back(m_path.at(k));
|
||||||
// First derivation element, get the fingerprint for origin
|
|
||||||
if (k == 0) {
|
|
||||||
std::copy(xprv.vchFingerprint, xprv.vchFingerprint + 4, origin.fingerprint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Build the remaining path
|
// Build the remaining path
|
||||||
KeyPath end_path;
|
KeyPath end_path;
|
||||||
for (; k < (int)m_path.size(); ++k) {
|
for (; k < (int)m_path.size(); ++k) {
|
||||||
end_path.push_back(m_path.at(k));
|
end_path.push_back(m_path.at(k));
|
||||||
}
|
}
|
||||||
|
// Get the fingerprint
|
||||||
|
CKeyID id = m_root_extkey.pubkey.GetID();
|
||||||
|
std::copy(id.begin(), id.begin() + 4, origin.fingerprint);
|
||||||
|
|
||||||
|
CExtPubKey xpub;
|
||||||
|
CExtKey lh_xprv;
|
||||||
|
// If we have the cache, just get the parent xpub
|
||||||
|
if (cache != nullptr) {
|
||||||
|
cache->GetCachedLastHardenedExtPubKey(m_expr_index, xpub);
|
||||||
|
}
|
||||||
|
if (!xpub.pubkey.IsValid()) {
|
||||||
|
// Cache miss, or nor cache, or need privkey
|
||||||
|
CExtKey xprv;
|
||||||
|
if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false;
|
||||||
|
xpub = lh_xprv.Neuter();
|
||||||
|
}
|
||||||
|
assert(xpub.pubkey.IsValid());
|
||||||
|
|
||||||
// Build the string
|
// Build the string
|
||||||
std::string origin_str = HexStr(origin.fingerprint) + FormatHDKeypath(origin.path);
|
std::string origin_str = HexStr(origin.fingerprint) + FormatHDKeypath(origin.path);
|
||||||
out = "[" + origin_str + "]" + EncodeExtPubKey(xprv.Neuter()) + FormatHDKeypath(end_path);
|
out = "[" + origin_str + "]" + EncodeExtPubKey(xpub) + FormatHDKeypath(end_path);
|
||||||
if (IsRange()) {
|
if (IsRange()) {
|
||||||
out += "/*";
|
out += "/*";
|
||||||
assert(m_derive == DeriveType::UNHARDENED);
|
assert(m_derive == DeriveType::UNHARDENED);
|
||||||
@@ -533,19 +543,19 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type) const
|
virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const
|
||||||
{
|
{
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
for (const auto& scriptarg : m_subdescriptor_args) {
|
for (const auto& scriptarg : m_subdescriptor_args) {
|
||||||
if (pos++) ret += ",";
|
if (pos++) ret += ",";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if (!scriptarg->ToStringHelper(arg, tmp, type)) return false;
|
if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) return false;
|
||||||
ret += std::move(tmp);
|
ret += std::move(tmp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type) const
|
bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type, const DescriptorCache* cache = nullptr) const
|
||||||
{
|
{
|
||||||
std::string extra = ToStringExtra();
|
std::string extra = ToStringExtra();
|
||||||
size_t pos = extra.size() > 0 ? 1 : 0;
|
size_t pos = extra.size() > 0 ? 1 : 0;
|
||||||
@@ -555,7 +565,7 @@ public:
|
|||||||
std::string tmp;
|
std::string tmp;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case StringType::NORMALIZED:
|
case StringType::NORMALIZED:
|
||||||
if (!pubkey->ToNormalizedString(*arg, tmp)) return false;
|
if (!pubkey->ToNormalizedString(*arg, tmp, cache)) return false;
|
||||||
break;
|
break;
|
||||||
case StringType::PRIVATE:
|
case StringType::PRIVATE:
|
||||||
if (!pubkey->ToPrivateString(*arg, tmp)) return false;
|
if (!pubkey->ToPrivateString(*arg, tmp)) return false;
|
||||||
@@ -567,7 +577,7 @@ public:
|
|||||||
ret += std::move(tmp);
|
ret += std::move(tmp);
|
||||||
}
|
}
|
||||||
std::string subscript;
|
std::string subscript;
|
||||||
if (!ToStringSubScriptHelper(arg, subscript, type)) return false;
|
if (!ToStringSubScriptHelper(arg, subscript, type, cache)) return false;
|
||||||
if (pos && subscript.size()) ret += ',';
|
if (pos && subscript.size()) ret += ',';
|
||||||
out = std::move(ret) + std::move(subscript) + ")";
|
out = std::move(ret) + std::move(subscript) + ")";
|
||||||
return true;
|
return true;
|
||||||
@@ -587,9 +597,9 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToNormalizedString(const SigningProvider& arg, std::string& out) const override final
|
bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override final
|
||||||
{
|
{
|
||||||
bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED);
|
bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
|
||||||
out = AddChecksum(out);
|
out = AddChecksum(out);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -843,7 +853,7 @@ protected:
|
|||||||
out.tr_spenddata[output].Merge(builder.GetSpendData());
|
out.tr_spenddata[output].Merge(builder.GetSpendData());
|
||||||
return Vector(GetScriptForDestination(output));
|
return Vector(GetScriptForDestination(output));
|
||||||
}
|
}
|
||||||
bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type) const override
|
bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const override
|
||||||
{
|
{
|
||||||
if (m_depths.empty()) return true;
|
if (m_depths.empty()) return true;
|
||||||
std::vector<bool> path;
|
std::vector<bool> path;
|
||||||
@@ -854,7 +864,7 @@ protected:
|
|||||||
path.push_back(false);
|
path.push_back(false);
|
||||||
}
|
}
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type)) return false;
|
if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)) return false;
|
||||||
ret += std::move(tmp);
|
ret += std::move(tmp);
|
||||||
while (!path.empty() && path.back()) {
|
while (!path.empty() && path.back()) {
|
||||||
if (path.size() > 1) ret += '}';
|
if (path.size() > 1) ret += '}';
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ struct Descriptor {
|
|||||||
virtual bool ToPrivateString(const SigningProvider& provider, std::string& out) const = 0;
|
virtual bool ToPrivateString(const SigningProvider& provider, std::string& out) const = 0;
|
||||||
|
|
||||||
/** Convert the descriptor to a normalized string. Normalized descriptors have the xpub at the last hardened step. This fails if the provided provider does not have the private keys to derive that xpub. */
|
/** Convert the descriptor to a normalized string. Normalized descriptors have the xpub at the last hardened step. This fails if the provided provider does not have the private keys to derive that xpub. */
|
||||||
virtual bool ToNormalizedString(const SigningProvider& provider, std::string& out) const = 0;
|
virtual bool ToNormalizedString(const SigningProvider& provider, std::string& out, const DescriptorCache* cache = nullptr) const = 0;
|
||||||
|
|
||||||
/** Expand a descriptor at a specified position.
|
/** Expand a descriptor at a specified position.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2276,7 +2276,7 @@ bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out) const
|
|||||||
FlatSigningProvider provider;
|
FlatSigningProvider provider;
|
||||||
provider.keys = GetKeys();
|
provider.keys = GetKeys();
|
||||||
|
|
||||||
return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out);
|
return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, &m_wallet_descriptor.cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorScriptPubKeyMan::UpgradeDescriptorCache()
|
void DescriptorScriptPubKeyMan::UpgradeDescriptorCache()
|
||||||
|
|||||||
Reference in new issue
Block a user