Return used destinations from ScriptPubKeyMan::MarkUnusedAddresses

pull/826/head
S3RK 3 years ago
parent 03840c2064
commit c1b99c088c

@ -354,15 +354,22 @@ bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t i
return true; return true;
} }
void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script) std::vector<WalletDestination> LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
{ {
LOCK(cs_KeyStore); LOCK(cs_KeyStore);
std::vector<WalletDestination> result;
// extract addresses and check if they match with an unused keypool key // extract addresses and check if they match with an unused keypool key
for (const auto& keyid : GetAffectedKeys(script, *this)) { for (const auto& keyid : GetAffectedKeys(script, *this)) {
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid); std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
if (mi != m_pool_key_to_index.end()) { if (mi != m_pool_key_to_index.end()) {
WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__); WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
MarkReserveKeysAsUsed(mi->second); for (const auto& keypool : MarkReserveKeysAsUsed(mi->second)) {
// derive all possible destinations as any of them could have been used
for (const auto& type : LEGACY_OUTPUT_TYPES) {
const auto& dest = GetDestinationForKey(keypool.vchPubKey, type);
result.push_back({dest, keypool.fInternal});
}
}
if (!TopUp()) { if (!TopUp()) {
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__); WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
@ -384,6 +391,8 @@ void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
} }
} }
} }
return result;
} }
void LegacyScriptPubKeyMan::UpgradeKeyMetadata() void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
@ -1427,7 +1436,7 @@ void LegacyScriptPubKeyMan::LearnAllRelatedScripts(const CPubKey& key)
LearnRelatedScripts(key, OutputType::P2SH_SEGWIT); LearnRelatedScripts(key, OutputType::P2SH_SEGWIT);
} }
void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id) std::vector<CKeyPool> LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
{ {
AssertLockHeld(cs_KeyStore); AssertLockHeld(cs_KeyStore);
bool internal = setInternalKeyPool.count(keypool_id); bool internal = setInternalKeyPool.count(keypool_id);
@ -1435,6 +1444,7 @@ void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : (set_pre_split_keypool.empty() ? &setExternalKeyPool : &set_pre_split_keypool); std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : (set_pre_split_keypool.empty() ? &setExternalKeyPool : &set_pre_split_keypool);
auto it = setKeyPool->begin(); auto it = setKeyPool->begin();
std::vector<CKeyPool> result;
WalletBatch batch(m_storage.GetDatabase()); WalletBatch batch(m_storage.GetDatabase());
while (it != std::end(*setKeyPool)) { while (it != std::end(*setKeyPool)) {
const int64_t& index = *(it); const int64_t& index = *(it);
@ -1448,7 +1458,10 @@ void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
batch.ErasePool(index); batch.ErasePool(index);
WalletLogPrintf("keypool index %d removed\n", index); WalletLogPrintf("keypool index %d removed\n", index);
it = setKeyPool->erase(it); it = setKeyPool->erase(it);
result.push_back(std::move(keypool));
} }
return result;
} }
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider) std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
@ -1820,19 +1833,32 @@ bool DescriptorScriptPubKeyMan::TopUp(unsigned int size)
return true; return true;
} }
void DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript& script) std::vector<WalletDestination> DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
{ {
LOCK(cs_desc_man); LOCK(cs_desc_man);
std::vector<WalletDestination> result;
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, mark all keypool items up to this item as used\n", __func__, index); WalletLogPrintf("%s: Detected a used keypool item at index %d, mark all keypool items up to this item as used\n", __func__, index);
m_wallet_descriptor.next_index = index + 1; auto out_keys = std::make_unique<FlatSigningProvider>();
std::vector<CScript> scripts_temp;
while (index >= m_wallet_descriptor.next_index) {
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) {
throw std::runtime_error(std::string(__func__) + ": Unable to expand descriptor from cache");
}
CTxDestination dest;
ExtractDestination(scripts_temp[0], dest);
result.push_back({dest, std::nullopt});
m_wallet_descriptor.next_index++;
}
} }
if (!TopUp()) { if (!TopUp()) {
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__); WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
} }
} }
return result;
} }
void DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey& key, const CPubKey &pubkey) void DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey& key, const CPubKey &pubkey)

@ -148,6 +148,12 @@ public:
} }
}; };
struct WalletDestination
{
CTxDestination dest;
std::optional<bool> internal;
};
/* /*
* A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet. * A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
* It contains the scripts and keys related to the scriptPubKeys it manages. * It contains the scripts and keys related to the scriptPubKeys it manages.
@ -180,8 +186,14 @@ public:
*/ */
virtual bool TopUp(unsigned int size = 0) { return false; } virtual bool TopUp(unsigned int size = 0) { return false; }
//! Mark unused addresses as being used /** Mark unused addresses as being used
virtual void MarkUnusedAddresses(const CScript& script) {} * Affects all keys up to and including the one determined by provided script.
*
* @param script determines the last key to mark as used
*
* @return All of the addresses affected
*/
virtual std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) { return {}; }
/** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active. /** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active.
* Returns false if already setup or setup fails, true if setup is successful * Returns false if already setup or setup fails, true if setup is successful
@ -356,7 +368,7 @@ public:
bool TopUp(unsigned int size = 0) override; bool TopUp(unsigned int size = 0) override;
void MarkUnusedAddresses(const CScript& script) override; std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
void UpgradeKeyMetadata(); void UpgradeKeyMetadata();
@ -481,9 +493,13 @@ public:
void LearnAllRelatedScripts(const CPubKey& key); void LearnAllRelatedScripts(const CPubKey& key);
/** /**
* Marks all keys in the keypool up to and including reserve_key as used. * Marks all keys in the keypool up to and including the provided key as used.
*
* @param keypool_id determines the last key to mark as used
*
* @return All affected keys
*/ */
void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); std::vector<CKeyPool> MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; } const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
std::set<CKeyID> GetKeys() const override; std::set<CKeyID> GetKeys() const override;
@ -563,7 +579,7 @@ public:
// (with or without private keys), the "keypool" is a single xpub. // (with or without private keys), the "keypool" is a single xpub.
bool TopUp(unsigned int size = 0) override; bool TopUp(unsigned int size = 0) override;
void MarkUnusedAddresses(const CScript& script) override; std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
bool IsHDEnabled() const override; bool IsHDEnabled() const override;

Loading…
Cancel
Save