Skip to content

Commit fcc2160

Browse files
committed
wallet: Cache SigningProviders
In order to avoid constantly re-deriving the same keys in DescriptorScriptPubKeyMan, cache the SigningProviders generated inside of GetSigningProvider. This makes GetSigningProvider non-const, which cauess a bunch of functions to also not be const and that results in a much larger diff than expected.
1 parent 7d64540 commit fcc2160

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

src/script/signingprovider.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvide
8282
return ret;
8383
}
8484

85+
void MergeInto(FlatSigningProvider& a, const FlatSigningProvider& b)
86+
{
87+
a.scripts.insert(b.scripts.begin(), b.scripts.end());
88+
a.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
89+
a.keys.insert(b.keys.begin(), b.keys.end());
90+
a.origins.insert(b.origins.begin(), b.origins.end());
91+
for (const auto& [output_key, spenddata] : b.tr_spenddata) {
92+
a.tr_spenddata[output_key].Merge(spenddata);
93+
}
94+
}
95+
8596
void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
8697
{
8798
AssertLockHeld(cs_KeyStore);

src/script/signingprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct FlatSigningProvider final : public SigningProvider
8585
};
8686

8787
FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b);
88+
void MergeInto(FlatSigningProvider& a, const FlatSigningProvider& b);
8889

8990
/** Fillable signing provider that keeps keys in an address->secret map */
9091
class FillableSigningProvider : public SigningProvider

src/wallet/scriptpubkeyman.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,10 +2076,22 @@ std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvid
20762076
std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
20772077
{
20782078
AssertLockHeld(cs_desc_man);
2079-
// Get the scripts, keys, and key origins for this script
2079+
20802080
std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
2081-
std::vector<CScript> scripts_temp;
2082-
if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
2081+
2082+
// Fetch SigningProvider from cache to avoid re-deriving
2083+
auto it = m_map_signing_providers.find(index);
2084+
if (it != m_map_signing_providers.end()) {
2085+
MergeInto(*out_keys, it->second);
2086+
} else {
2087+
// Get the scripts, keys, and key origins for this script
2088+
std::vector<CScript> scripts_temp;
2089+
if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
2090+
2091+
// Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
2092+
m_map_signing_providers.insert({index, {}});
2093+
MergeInto(m_map_signing_providers[index], *out_keys);
2094+
}
20832095

20842096
if (HavePrivateKeys() && include_private) {
20852097
FlatSigningProvider master_provider;

src/wallet/scriptpubkeyman.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
546546

547547
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
548548

549+
// Cached FlatSigningProviders to avoid regenerating them each time they are needed.
550+
mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
549551
// Fetch the SigningProvider for the given script and optionally include private keys
550552
std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
551553
// Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.

0 commit comments

Comments
 (0)