Cache parent xpub inside of BIP32PubkeyProvider
Optimize Expand by having BIP32PubkeyProvider also cache the parent (or only) xpub within itself. Since Expand does not provide a read cache, it is useful to internally cache this xpub to avoid re-deriving the same xpub.
This commit is contained in:
1 parent
deb791c7ba
commit
09e25071f4
1 file changed
+15
-4
@@ -165,7 +165,7 @@ public:
|
|||||||
* write_cache is the cache to write keys to (if not nullptr)
|
* write_cache is the cache to write keys to (if not nullptr)
|
||||||
* Caches are not exclusive but this is not tested. Currently we use them exclusively
|
* Caches are not exclusive but this is not tested. Currently we use them exclusively
|
||||||
*/
|
*/
|
||||||
virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const = 0;
|
virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) = 0;
|
||||||
|
|
||||||
/** Whether this represent multiple public keys at different positions. */
|
/** Whether this represent multiple public keys at different positions. */
|
||||||
virtual bool IsRange() const = 0;
|
virtual bool IsRange() const = 0;
|
||||||
@@ -195,7 +195,7 @@ class OriginPubkeyProvider final : public PubkeyProvider
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
|
OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
|
||||||
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
|
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
|
||||||
{
|
{
|
||||||
if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
|
if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
|
||||||
std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
|
std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
|
||||||
@@ -225,7 +225,7 @@ class ConstPubkeyProvider final : public PubkeyProvider
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
|
ConstPubkeyProvider(uint32_t exp_index, const CPubKey& pubkey) : PubkeyProvider(exp_index), m_pubkey(pubkey) {}
|
||||||
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
|
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
|
||||||
{
|
{
|
||||||
key = m_pubkey;
|
key = m_pubkey;
|
||||||
info.path.clear();
|
info.path.clear();
|
||||||
@@ -262,6 +262,9 @@ class BIP32PubkeyProvider final : public PubkeyProvider
|
|||||||
CExtPubKey m_root_extkey;
|
CExtPubKey m_root_extkey;
|
||||||
KeyPath m_path;
|
KeyPath m_path;
|
||||||
DeriveType m_derive;
|
DeriveType m_derive;
|
||||||
|
// Cache of the parent of the final derived pubkeys.
|
||||||
|
// Primarily useful for situations when no read_cache is provided
|
||||||
|
CExtPubKey m_cached_xpub;
|
||||||
|
|
||||||
bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
|
bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
|
||||||
{
|
{
|
||||||
@@ -298,7 +301,7 @@ public:
|
|||||||
BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
|
BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
|
||||||
bool IsRange() const override { return m_derive != DeriveType::NO; }
|
bool IsRange() const override { return m_derive != DeriveType::NO; }
|
||||||
size_t GetSize() const override { return 33; }
|
size_t GetSize() const override { return 33; }
|
||||||
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
|
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) override
|
||||||
{
|
{
|
||||||
// Info of parent of the to be derived pubkey
|
// Info of parent of the to be derived pubkey
|
||||||
KeyOriginInfo parent_info;
|
KeyOriginInfo parent_info;
|
||||||
@@ -323,6 +326,9 @@ public:
|
|||||||
final_extkey = parent_extkey;
|
final_extkey = parent_extkey;
|
||||||
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
|
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
|
||||||
}
|
}
|
||||||
|
} else if (m_cached_xpub.pubkey.IsValid() && m_derive != DeriveType::HARDENED) {
|
||||||
|
parent_extkey = final_extkey = m_cached_xpub;
|
||||||
|
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
|
||||||
} else if (IsHardened()) {
|
} else if (IsHardened()) {
|
||||||
CExtKey xprv;
|
CExtKey xprv;
|
||||||
if (!GetDerivedExtKey(arg, xprv)) return false;
|
if (!GetDerivedExtKey(arg, xprv)) return false;
|
||||||
@@ -344,6 +350,11 @@ public:
|
|||||||
final_info_out = final_info_out_tmp;
|
final_info_out = final_info_out_tmp;
|
||||||
key_out = final_extkey.pubkey;
|
key_out = final_extkey.pubkey;
|
||||||
|
|
||||||
|
// We rely on the consumer to check that m_derive isn't HARDENED as above
|
||||||
|
// But we can't have already cached something in case we read something from the cache
|
||||||
|
// and parent_extkey isn't actually the parent.
|
||||||
|
if (!m_cached_xpub.pubkey.IsValid()) m_cached_xpub = parent_extkey;
|
||||||
|
|
||||||
if (write_cache) {
|
if (write_cache) {
|
||||||
// Only cache parent if there is any unhardened derivation
|
// Only cache parent if there is any unhardened derivation
|
||||||
if (m_derive != DeriveType::HARDENED) {
|
if (m_derive != DeriveType::HARDENED) {
|
||||||
|
|||||||
Reference in new issue
Block a user