From 1f798fe85ba952273005f68e36ed48cfc36f4c9d Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Mon, 28 Mar 2022 16:47:59 -0400 Subject: [PATCH] wallet: Cache SigningProviders In order to avoid constantly re-deriving the same keys in DescriptorScriptPubKeyMan, cache the SigningProviders generated inside of GetSigningProvider. --- src/wallet/scriptpubkeyman.cpp | 17 ++++++++++++++--- src/wallet/scriptpubkeyman.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index bba31dfe0b..a0efc4c063 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -2075,10 +2075,21 @@ std::unique_ptr DescriptorScriptPubKeyMan::GetSigningProvid std::unique_ptr DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const { AssertLockHeld(cs_desc_man); - // Get the scripts, keys, and key origins for this script + std::unique_ptr out_keys = std::make_unique(); - std::vector scripts_temp; - if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr; + + // Fetch SigningProvider from cache to avoid re-deriving + auto it = m_map_signing_providers.find(index); + if (it != m_map_signing_providers.end()) { + *out_keys = Merge(*out_keys, it->second); + } else { + // Get the scripts, keys, and key origins for this script + std::vector scripts_temp; + if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr; + + // Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again + m_map_signing_providers[index] = *out_keys; + } if (HavePrivateKeys() && include_private) { FlatSigningProvider master_provider; diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index eebc05330f..d0af09463b 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -547,6 +547,8 @@ private: KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man); + // Cached FlatSigningProviders to avoid regenerating them each time they are needed. + mutable std::map m_map_signing_providers; // Fetch the SigningProvider for the given script and optionally include private keys std::unique_ptr GetSigningProvider(const CScript& script, bool include_private = false) const; // Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.