Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/scriptpubkeyman.cpp
Show First 20 Lines • Show All 1,548 Lines • ▼ Show 20 Lines | bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, | ||||
int64_t &index, | int64_t &index, | ||||
CKeyPool &keypool) { | CKeyPool &keypool) { | ||||
return false; | return false; | ||||
} | } | ||||
void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, | void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, | ||||
const CTxDestination &addr) {} | const CTxDestination &addr) {} | ||||
std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const { | |||||
AssertLockHeld(cs_desc_man); | |||||
if (m_storage.HasEncryptionKeys() && !m_storage.IsLocked()) { | |||||
KeyMap keys; | |||||
for (auto key_pair : m_map_crypted_keys) { | |||||
const CPubKey &pubkey = key_pair.second.first; | |||||
const std::vector<uint8_t> &crypted_secret = key_pair.second.second; | |||||
CKey key; | |||||
DecryptKey(m_storage.GetEncryptionKey(), crypted_secret, pubkey, | |||||
key); | |||||
keys[pubkey.GetID()] = key; | |||||
} | |||||
return keys; | |||||
} | |||||
return m_map_keys; | |||||
} | |||||
bool DescriptorScriptPubKeyMan::TopUp(unsigned int size) { | bool DescriptorScriptPubKeyMan::TopUp(unsigned int size) { | ||||
LOCK(cs_desc_man); | |||||
unsigned int target_size; | |||||
if (size > 0) { | |||||
target_size = size; | |||||
} else { | |||||
target_size = std::max(gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), | |||||
int64_t(1)); | |||||
} | |||||
// Calculate the new range_end | |||||
int32_t new_range_end = | |||||
std::max(m_wallet_descriptor.next_index + int32_t(target_size), | |||||
m_wallet_descriptor.range_end); | |||||
// If the descriptor is not ranged, we actually just want to fill the first | |||||
// cache item | |||||
if (!m_wallet_descriptor.descriptor->IsRange()) { | |||||
new_range_end = 1; | |||||
m_wallet_descriptor.range_end = 1; | |||||
m_wallet_descriptor.range_start = 0; | |||||
} | |||||
FlatSigningProvider provider; | |||||
provider.keys = GetKeys(); | |||||
WalletBatch batch(m_storage.GetDatabase()); | |||||
uint256 id = GetID(); | |||||
for (int32_t i = m_max_cached_index + 1; i < new_range_end; ++i) { | |||||
FlatSigningProvider out_keys; | |||||
std::vector<CScript> scripts_temp; | |||||
DescriptorCache temp_cache; | |||||
// Maybe we have a cached xpub and we can expand from the cache first | |||||
if (!m_wallet_descriptor.descriptor->ExpandFromCache( | |||||
i, m_wallet_descriptor.cache, scripts_temp, out_keys)) { | |||||
if (!m_wallet_descriptor.descriptor->Expand( | |||||
i, provider, scripts_temp, out_keys, &temp_cache)) { | |||||
return false; | return false; | ||||
} | } | ||||
} | |||||
// Add all of the scriptPubKeys to the scriptPubKey set | |||||
for (const CScript &script : scripts_temp) { | |||||
m_map_script_pub_keys[script] = i; | |||||
} | |||||
// Write the cache | |||||
for (const auto &parent_xpub_pair : | |||||
temp_cache.GetCachedParentExtPubKeys()) { | |||||
CExtPubKey xpub; | |||||
if (m_wallet_descriptor.cache.GetCachedParentExtPubKey( | |||||
parent_xpub_pair.first, xpub)) { | |||||
if (xpub != parent_xpub_pair.second) { | |||||
throw std::runtime_error( | |||||
std::string(__func__) + | |||||
": New cached parent xpub does not match already " | |||||
"cached parent xpub"); | |||||
} | |||||
continue; | |||||
} | |||||
if (!batch.WriteDescriptorParentCache(parent_xpub_pair.second, id, | |||||
parent_xpub_pair.first)) { | |||||
throw std::runtime_error(std::string(__func__) + | |||||
": writing cache item failed"); | |||||
} | |||||
m_wallet_descriptor.cache.CacheParentExtPubKey( | |||||
parent_xpub_pair.first, parent_xpub_pair.second); | |||||
} | |||||
for (const auto &derived_xpub_map_pair : | |||||
temp_cache.GetCachedDerivedExtPubKeys()) { | |||||
for (const auto &derived_xpub_pair : derived_xpub_map_pair.second) { | |||||
CExtPubKey xpub; | |||||
if (m_wallet_descriptor.cache.GetCachedDerivedExtPubKey( | |||||
derived_xpub_map_pair.first, derived_xpub_pair.first, | |||||
xpub)) { | |||||
if (xpub != derived_xpub_pair.second) { | |||||
throw std::runtime_error( | |||||
std::string(__func__) + | |||||
": New cached derived xpub does not match already " | |||||
"cached derived xpub"); | |||||
} | |||||
continue; | |||||
} | |||||
if (!batch.WriteDescriptorDerivedCache( | |||||
derived_xpub_pair.second, id, | |||||
derived_xpub_map_pair.first, derived_xpub_pair.first)) { | |||||
throw std::runtime_error(std::string(__func__) + | |||||
": writing cache item failed"); | |||||
} | |||||
m_wallet_descriptor.cache.CacheDerivedExtPubKey( | |||||
derived_xpub_map_pair.first, derived_xpub_pair.first, | |||||
derived_xpub_pair.second); | |||||
} | |||||
} | |||||
m_max_cached_index++; | |||||
} | |||||
m_wallet_descriptor.range_end = new_range_end; | |||||
batch.WriteDescriptor(GetID(), m_wallet_descriptor); | |||||
// By this point, the cache size should be the size of the entire range | |||||
assert(m_wallet_descriptor.range_end - 1 == m_max_cached_index); | |||||
NotifyCanGetAddressesChanged(); | |||||
return true; | |||||
} | |||||
void DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript &script) { | void DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript &script) { | ||||
LOCK(cs_desc_man); | LOCK(cs_desc_man); | ||||
if (IsMine(script)) { | if (IsMine(script)) { | ||||
int32_t index = m_map_script_pub_keys[script]; | int32_t index = m_map_script_pub_keys[script]; | ||||
if (index >= m_wallet_descriptor.next_index) { | if (index >= m_wallet_descriptor.next_index) { | ||||
WalletLogPrintf("%s: Detected a used keypool item at index %d, " | WalletLogPrintf("%s: Detected a used keypool item at index %d, " | ||||
"mark all keypool items up to this item as used\n", | "mark all keypool items up to this item as used\n", | ||||
▲ Show 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | for (int32_t i = m_wallet_descriptor.range_start; | ||||
if (m_map_script_pub_keys.count(script) != 0) { | if (m_map_script_pub_keys.count(script) != 0) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
strprintf("Error: Already loaded script at index %d as " | strprintf("Error: Already loaded script at index %d as " | ||||
"being at index %d", | "being at index %d", | ||||
i, m_map_script_pub_keys[script])); | i, m_map_script_pub_keys[script])); | ||||
} | } | ||||
m_map_script_pub_keys[script] = i; | m_map_script_pub_keys[script] = i; | ||||
} | } | ||||
m_max_cached_index++; | |||||
} | } | ||||
} | } | ||||
bool DescriptorScriptPubKeyMan::AddKey(const CKeyID &key_id, const CKey &key) { | bool DescriptorScriptPubKeyMan::AddKey(const CKeyID &key_id, const CKey &key) { | ||||
LOCK(cs_desc_man); | LOCK(cs_desc_man); | ||||
m_map_keys[key_id] = key; | m_map_keys[key_id] = key; | ||||
return true; | return true; | ||||
} | } | ||||
Show All 12 Lines |