Skip to content

Commit c1b99c0

Browse files
committed
Return used destinations from ScriptPubKeyMan::MarkUnusedAddresses
1 parent 03840c2 commit c1b99c0

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

src/wallet/scriptpubkeyman.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,15 +354,22 @@ bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t i
354354
return true;
355355
}
356356

357-
void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
357+
std::vector<WalletDestination> LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
358358
{
359359
LOCK(cs_KeyStore);
360+
std::vector<WalletDestination> result;
360361
// extract addresses and check if they match with an unused keypool key
361362
for (const auto& keyid : GetAffectedKeys(script, *this)) {
362363
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
363364
if (mi != m_pool_key_to_index.end()) {
364365
WalletLogPrintf("%s: Detected a used keypool key, mark all keypool keys up to this key as used\n", __func__);
365-
MarkReserveKeysAsUsed(mi->second);
366+
for (const auto& keypool : MarkReserveKeysAsUsed(mi->second)) {
367+
// derive all possible destinations as any of them could have been used
368+
for (const auto& type : LEGACY_OUTPUT_TYPES) {
369+
const auto& dest = GetDestinationForKey(keypool.vchPubKey, type);
370+
result.push_back({dest, keypool.fInternal});
371+
}
372+
}
366373

367374
if (!TopUp()) {
368375
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
@@ -384,6 +391,8 @@ void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
384391
}
385392
}
386393
}
394+
395+
return result;
387396
}
388397

389398
void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
@@ -1427,14 +1436,15 @@ void LegacyScriptPubKeyMan::LearnAllRelatedScripts(const CPubKey& key)
14271436
LearnRelatedScripts(key, OutputType::P2SH_SEGWIT);
14281437
}
14291438

1430-
void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
1439+
std::vector<CKeyPool> LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
14311440
{
14321441
AssertLockHeld(cs_KeyStore);
14331442
bool internal = setInternalKeyPool.count(keypool_id);
14341443
if (!internal) assert(setExternalKeyPool.count(keypool_id) || set_pre_split_keypool.count(keypool_id));
14351444
std::set<int64_t> *setKeyPool = internal ? &setInternalKeyPool : (set_pre_split_keypool.empty() ? &setExternalKeyPool : &set_pre_split_keypool);
14361445
auto it = setKeyPool->begin();
14371446

1447+
std::vector<CKeyPool> result;
14381448
WalletBatch batch(m_storage.GetDatabase());
14391449
while (it != std::end(*setKeyPool)) {
14401450
const int64_t& index = *(it);
@@ -1448,7 +1458,10 @@ void LegacyScriptPubKeyMan::MarkReserveKeysAsUsed(int64_t keypool_id)
14481458
batch.ErasePool(index);
14491459
WalletLogPrintf("keypool index %d removed\n", index);
14501460
it = setKeyPool->erase(it);
1461+
result.push_back(std::move(keypool));
14511462
}
1463+
1464+
return result;
14521465
}
14531466

14541467
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
@@ -1820,19 +1833,32 @@ bool DescriptorScriptPubKeyMan::TopUp(unsigned int size)
18201833
return true;
18211834
}
18221835

1823-
void DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
1836+
std::vector<WalletDestination> DescriptorScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
18241837
{
18251838
LOCK(cs_desc_man);
1839+
std::vector<WalletDestination> result;
18261840
if (IsMine(script)) {
18271841
int32_t index = m_map_script_pub_keys[script];
18281842
if (index >= m_wallet_descriptor.next_index) {
18291843
WalletLogPrintf("%s: Detected a used keypool item at index %d, mark all keypool items up to this item as used\n", __func__, index);
1830-
m_wallet_descriptor.next_index = index + 1;
1844+
auto out_keys = std::make_unique<FlatSigningProvider>();
1845+
std::vector<CScript> scripts_temp;
1846+
while (index >= m_wallet_descriptor.next_index) {
1847+
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) {
1848+
throw std::runtime_error(std::string(__func__) + ": Unable to expand descriptor from cache");
1849+
}
1850+
CTxDestination dest;
1851+
ExtractDestination(scripts_temp[0], dest);
1852+
result.push_back({dest, std::nullopt});
1853+
m_wallet_descriptor.next_index++;
1854+
}
18311855
}
18321856
if (!TopUp()) {
18331857
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
18341858
}
18351859
}
1860+
1861+
return result;
18361862
}
18371863

18381864
void DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey& key, const CPubKey &pubkey)

src/wallet/scriptpubkeyman.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ class CKeyPool
148148
}
149149
};
150150

151+
struct WalletDestination
152+
{
153+
CTxDestination dest;
154+
std::optional<bool> internal;
155+
};
156+
151157
/*
152158
* A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
153159
* It contains the scripts and keys related to the scriptPubKeys it manages.
@@ -180,8 +186,14 @@ class ScriptPubKeyMan
180186
*/
181187
virtual bool TopUp(unsigned int size = 0) { return false; }
182188

183-
//! Mark unused addresses as being used
184-
virtual void MarkUnusedAddresses(const CScript& script) {}
189+
/** Mark unused addresses as being used
190+
* Affects all keys up to and including the one determined by provided script.
191+
*
192+
* @param script determines the last key to mark as used
193+
*
194+
* @return All of the addresses affected
195+
*/
196+
virtual std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) { return {}; }
185197

186198
/** Sets up the key generation stuff, i.e. generates new HD seeds and sets them as active.
187199
* Returns false if already setup or setup fails, true if setup is successful
@@ -356,7 +368,7 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv
356368

357369
bool TopUp(unsigned int size = 0) override;
358370

359-
void MarkUnusedAddresses(const CScript& script) override;
371+
std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
360372

361373
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
362374
void UpgradeKeyMetadata();
@@ -481,9 +493,13 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv
481493
void LearnAllRelatedScripts(const CPubKey& key);
482494

483495
/**
484-
* Marks all keys in the keypool up to and including reserve_key as used.
496+
* Marks all keys in the keypool up to and including the provided key as used.
497+
*
498+
* @param keypool_id determines the last key to mark as used
499+
*
500+
* @return All affected keys
485501
*/
486-
void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
502+
std::vector<CKeyPool> MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
487503
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
488504

489505
std::set<CKeyID> GetKeys() const override;
@@ -563,7 +579,7 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
563579
// (with or without private keys), the "keypool" is a single xpub.
564580
bool TopUp(unsigned int size = 0) override;
565581

566-
void MarkUnusedAddresses(const CScript& script) override;
582+
std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
567583

568584
bool IsHDEnabled() const override;
569585

0 commit comments

Comments
 (0)