mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-01 10:43:10 +02:00
descriptors: Cache last hardened xpub
Cache the last hardenex xpub in the DescriptorCache
This commit is contained in:
parent
cacc391098
commit
d87b544b83
@ -302,11 +302,14 @@ class BIP32PubkeyProvider final : public PubkeyProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Derives the last xprv
|
// Derives the last xprv
|
||||||
bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv) const
|
bool GetDerivedExtKey(const SigningProvider& arg, CExtKey& xprv, CExtKey& last_hardened) const
|
||||||
{
|
{
|
||||||
if (!GetExtKey(arg, xprv)) return false;
|
if (!GetExtKey(arg, xprv)) return false;
|
||||||
for (auto entry : m_path) {
|
for (auto entry : m_path) {
|
||||||
xprv.Derive(xprv, entry);
|
xprv.Derive(xprv, entry);
|
||||||
|
if (entry >> 31) {
|
||||||
|
last_hardened = xprv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -340,6 +343,7 @@ public:
|
|||||||
// Derive keys or fetch them from cache
|
// Derive keys or fetch them from cache
|
||||||
CExtPubKey final_extkey = m_root_extkey;
|
CExtPubKey final_extkey = m_root_extkey;
|
||||||
CExtPubKey parent_extkey = m_root_extkey;
|
CExtPubKey parent_extkey = m_root_extkey;
|
||||||
|
CExtPubKey last_hardened_extkey;
|
||||||
bool der = true;
|
bool der = true;
|
||||||
if (read_cache) {
|
if (read_cache) {
|
||||||
if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
|
if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
|
||||||
@ -351,11 +355,15 @@ public:
|
|||||||
}
|
}
|
||||||
} else if (IsHardened()) {
|
} else if (IsHardened()) {
|
||||||
CExtKey xprv;
|
CExtKey xprv;
|
||||||
if (!GetDerivedExtKey(arg, xprv)) return false;
|
CExtKey lh_xprv;
|
||||||
|
if (!GetDerivedExtKey(arg, xprv, lh_xprv)) return false;
|
||||||
parent_extkey = xprv.Neuter();
|
parent_extkey = xprv.Neuter();
|
||||||
if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
|
if (m_derive == DeriveType::UNHARDENED) der = xprv.Derive(xprv, pos);
|
||||||
if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
|
if (m_derive == DeriveType::HARDENED) der = xprv.Derive(xprv, pos | 0x80000000UL);
|
||||||
final_extkey = xprv.Neuter();
|
final_extkey = xprv.Neuter();
|
||||||
|
if (lh_xprv.key.IsValid()) {
|
||||||
|
last_hardened_extkey = lh_xprv.Neuter();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto entry : m_path) {
|
for (auto entry : m_path) {
|
||||||
der = parent_extkey.Derive(parent_extkey, entry);
|
der = parent_extkey.Derive(parent_extkey, entry);
|
||||||
@ -374,6 +382,10 @@ public:
|
|||||||
// 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) {
|
||||||
write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
|
write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
|
||||||
|
// Cache last hardened xpub if we have it
|
||||||
|
if (last_hardened_extkey.pubkey.IsValid()) {
|
||||||
|
write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
|
||||||
|
}
|
||||||
} else if (final_info_out.path.size() > 0) {
|
} else if (final_info_out.path.size() > 0) {
|
||||||
write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
|
write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
|
||||||
}
|
}
|
||||||
@ -454,7 +466,8 @@ public:
|
|||||||
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
|
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
|
||||||
{
|
{
|
||||||
CExtKey extkey;
|
CExtKey extkey;
|
||||||
if (!GetDerivedExtKey(arg, extkey)) return false;
|
CExtKey dummy;
|
||||||
|
if (!GetDerivedExtKey(arg, extkey, dummy)) return false;
|
||||||
if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
|
if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
|
||||||
if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
|
if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
|
||||||
key = extkey.key;
|
key = extkey.key;
|
||||||
@ -1400,6 +1413,11 @@ void DescriptorCache::CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_i
|
|||||||
xpubs[der_index] = xpub;
|
xpubs[der_index] = xpub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DescriptorCache::CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub)
|
||||||
|
{
|
||||||
|
m_last_hardened_xpubs[key_exp_pos] = xpub;
|
||||||
|
}
|
||||||
|
|
||||||
bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
|
bool DescriptorCache::GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
|
||||||
{
|
{
|
||||||
const auto& it = m_parent_xpubs.find(key_exp_pos);
|
const auto& it = m_parent_xpubs.find(key_exp_pos);
|
||||||
@ -1418,6 +1436,14 @@ bool DescriptorCache::GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t d
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DescriptorCache::GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const
|
||||||
|
{
|
||||||
|
const auto& it = m_last_hardened_xpubs.find(key_exp_pos);
|
||||||
|
if (it == m_last_hardened_xpubs.end()) return false;
|
||||||
|
xpub = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DescriptorCache DescriptorCache::MergeAndDiff(const DescriptorCache& other)
|
DescriptorCache DescriptorCache::MergeAndDiff(const DescriptorCache& other)
|
||||||
{
|
{
|
||||||
DescriptorCache diff;
|
DescriptorCache diff;
|
||||||
@ -1445,6 +1471,17 @@ DescriptorCache DescriptorCache::MergeAndDiff(const DescriptorCache& other)
|
|||||||
diff.CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
|
diff.CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto& lh_xpub_pair : other.GetCachedLastHardenedExtPubKeys()) {
|
||||||
|
CExtPubKey xpub;
|
||||||
|
if (GetCachedLastHardenedExtPubKey(lh_xpub_pair.first, xpub)) {
|
||||||
|
if (xpub != lh_xpub_pair.second) {
|
||||||
|
throw std::runtime_error(std::string(__func__) + ": New cached last hardened xpub does not match already cached last hardened xpub");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CacheLastHardenedExtPubKey(lh_xpub_pair.first, lh_xpub_pair.second);
|
||||||
|
diff.CacheLastHardenedExtPubKey(lh_xpub_pair.first, lh_xpub_pair.second);
|
||||||
|
}
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1457,3 +1494,8 @@ const std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDeriv
|
|||||||
{
|
{
|
||||||
return m_derived_xpubs;
|
return m_derived_xpubs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExtPubKeyMap DescriptorCache::GetCachedLastHardenedExtPubKeys() const
|
||||||
|
{
|
||||||
|
return m_last_hardened_xpubs;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,8 @@ private:
|
|||||||
std::unordered_map<uint32_t, ExtPubKeyMap> m_derived_xpubs;
|
std::unordered_map<uint32_t, ExtPubKeyMap> m_derived_xpubs;
|
||||||
/** Map key expression index -> parent xpub */
|
/** Map key expression index -> parent xpub */
|
||||||
ExtPubKeyMap m_parent_xpubs;
|
ExtPubKeyMap m_parent_xpubs;
|
||||||
|
/** Map key expression index -> last hardened xpub */
|
||||||
|
ExtPubKeyMap m_last_hardened_xpubs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Cache a parent xpub
|
/** Cache a parent xpub
|
||||||
@ -50,11 +52,25 @@ public:
|
|||||||
* @param[in] xpub The CExtPubKey to get from cache
|
* @param[in] xpub The CExtPubKey to get from cache
|
||||||
*/
|
*/
|
||||||
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const;
|
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const;
|
||||||
|
/** Cache a last hardened xpub
|
||||||
|
*
|
||||||
|
* @param[in] key_exp_pos Position of the key expression within the descriptor
|
||||||
|
* @param[in] xpub The CExtPubKey to cache
|
||||||
|
*/
|
||||||
|
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub);
|
||||||
|
/** Retrieve a cached last hardened xpub
|
||||||
|
*
|
||||||
|
* @param[in] key_exp_pos Position of the key expression within the descriptor
|
||||||
|
* @param[in] xpub The CExtPubKey to get from cache
|
||||||
|
*/
|
||||||
|
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const;
|
||||||
|
|
||||||
/** Retrieve all cached parent xpubs */
|
/** Retrieve all cached parent xpubs */
|
||||||
const ExtPubKeyMap GetCachedParentExtPubKeys() const;
|
const ExtPubKeyMap GetCachedParentExtPubKeys() const;
|
||||||
/** Retrieve all cached derived xpubs */
|
/** Retrieve all cached derived xpubs */
|
||||||
const std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;
|
const std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;
|
||||||
|
/** Retrieve all cached last hardened xpubs */
|
||||||
|
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const;
|
||||||
|
|
||||||
/** Combine another DescriptorCache into this one.
|
/** Combine another DescriptorCache into this one.
|
||||||
* Returns a cache containing the items from the other cache unknown to current cache
|
* Returns a cache containing the items from the other cache unknown to current cache
|
||||||
|
Loading…
x
Reference in New Issue
Block a user