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.
pull/826/head
Andrew Chow 4 years ago
parent 7a26ff10c2
commit 3280704886

@ -181,7 +181,7 @@ public:
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
/** 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. */
virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
@ -216,10 +216,10 @@ public:
ret = "[" + OriginString() + "]" + std::move(sub);
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;
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
// 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.
@ -263,7 +263,7 @@ public:
ret = EncodeSecret(key);
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();
return true;
@ -412,7 +412,7 @@ public:
}
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
if (m_derive == DeriveType::HARDENED) {
@ -431,29 +431,39 @@ public:
out = ToString();
return true;
}
// Derive the xpub at the last hardened step
CExtKey xprv;
if (!GetExtKey(arg, xprv)) return false;
// Get the path to the last hardened stup
KeyOriginInfo origin;
int k = 0;
for (; k <= i; ++k) {
// Derive
xprv.Derive(xprv, m_path.at(k));
// Add to the path
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
KeyPath end_path;
for (; k < (int)m_path.size(); ++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
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()) {
out += "/*";
assert(m_derive == DeriveType::UNHARDENED);
@ -533,19 +543,19 @@ public:
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;
for (const auto& scriptarg : m_subdescriptor_args) {
if (pos++) ret += ",";
std::string tmp;
if (!scriptarg->ToStringHelper(arg, tmp, type)) return false;
if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) return false;
ret += std::move(tmp);
}
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();
size_t pos = extra.size() > 0 ? 1 : 0;
@ -555,7 +565,7 @@ public:
std::string tmp;
switch (type) {
case StringType::NORMALIZED:
if (!pubkey->ToNormalizedString(*arg, tmp)) return false;
if (!pubkey->ToNormalizedString(*arg, tmp, cache)) return false;
break;
case StringType::PRIVATE:
if (!pubkey->ToPrivateString(*arg, tmp)) return false;
@ -567,7 +577,7 @@ public:
ret += std::move(tmp);
}
std::string subscript;
if (!ToStringSubScriptHelper(arg, subscript, type)) return false;
if (!ToStringSubScriptHelper(arg, subscript, type, cache)) return false;
if (pos && subscript.size()) ret += ',';
out = std::move(ret) + std::move(subscript) + ")";
return true;
@ -587,9 +597,9 @@ public:
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);
return ret;
}
@ -843,7 +853,7 @@ protected:
out.tr_spenddata[output].Merge(builder.GetSpendData());
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;
std::vector<bool> path;
@ -854,7 +864,7 @@ protected:
path.push_back(false);
}
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);
while (!path.empty() && path.back()) {
if (path.size() > 1) ret += '}';

@ -115,7 +115,7 @@ struct Descriptor {
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. */
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.
*

@ -2276,7 +2276,7 @@ bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out) const
FlatSigningProvider provider;
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()

Loading…
Cancel
Save