Skip to content

Commit 3efaf83

Browse files
committed
wallet: deactivate descriptor
1 parent 6737d96 commit 3efaf83

File tree

6 files changed

+49
-0
lines changed

6 files changed

+49
-0
lines changed

src/wallet/rpcdump.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,10 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
15841584
} else {
15851585
wallet.AddActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.descriptor->GetOutputType(), internal);
15861586
}
1587+
} else {
1588+
if (w_desc.descriptor->GetOutputType()) {
1589+
wallet.DeactivateScriptPubKeyMan(spk_manager->GetID(), *w_desc.descriptor->GetOutputType(), internal);
1590+
}
15871591
}
15881592

15891593
result.pushKV("success", UniValue(true));

src/wallet/wallet.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -3171,6 +3171,23 @@ void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool intern
31713171
NotifyCanGetAddressesChanged();
31723172
}
31733173

3174+
void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3175+
{
3176+
auto spk_man = GetScriptPubKeyMan(type, internal);
3177+
if (spk_man != nullptr && spk_man->GetID() == id) {
3178+
WalletLogPrintf("Deactivate spkMan: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3179+
WalletBatch batch(GetDatabase());
3180+
if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3181+
throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3182+
}
3183+
3184+
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3185+
spk_mans[type] = nullptr;
3186+
}
3187+
3188+
NotifyCanGetAddressesChanged();
3189+
}
3190+
31743191
bool CWallet::IsLegacy() const
31753192
{
31763193
if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) {

src/wallet/wallet.h

+6
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,12 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
895895
//! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
896896
void LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal);
897897

898+
//! Remove specified ScriptPubKeyMan from set of active SPK managers. Writes the change to the wallet file.
899+
//! @param[in] id The unique id for the ScriptPubKeyMan
900+
//! @param[in] type The OutputType this ScriptPubKeyMan provides addresses for
901+
//! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
902+
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal);
903+
898904
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
899905
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
900906

src/wallet/walletdb.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bo
209209
return WriteIC(make_pair(key, type), id);
210210
}
211211

212+
bool WalletBatch::EraseActiveScriptPubKeyMan(uint8_t type, bool internal)
213+
{
214+
const std::string key{internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK};
215+
return EraseIC(make_pair(key, type));
216+
}
217+
212218
bool WalletBatch::WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey)
213219
{
214220
// hash pubkey/privkey to accelerate wallet load

src/wallet/walletdb.h

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class WalletBatch
253253
bool EraseDestData(const std::string &address, const std::string &key);
254254

255255
bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal);
256+
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal);
256257

257258
DBErrors LoadWallet(CWallet* pwallet);
258259
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx);

test/functional/wallet_importdescriptors.py

+15
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,21 @@ def run_test(self):
372372
address = w1.getrawchangeaddress('legacy')
373373
assert_equal(address, "mpA2Wh9dvZT7yfELq1UnrUmAoc5qCkMetg")
374374

375+
self.log.info('Check can deactivate active descriptor')
376+
self.test_importdesc({'desc': descsum_create('pkh([12345678]' + xpub + '/*)'),
377+
'range': [0, 5],
378+
'active': False,
379+
'timestamp': 'now',
380+
'internal': True
381+
},
382+
success=True)
383+
assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'legacy')
384+
385+
self.log.info('Verify activation state is persistent')
386+
w1.unloadwallet()
387+
self.nodes[1].loadwallet('w1')
388+
assert_raises_rpc_error(-4, 'This wallet has no available keys', w1.getrawchangeaddress, 'legacy')
389+
375390
# # Test importing a descriptor containing a WIF private key
376391
wif_priv = "cTe1f5rdT8A8DFgVWTjyPwACsDPJM9ff4QngFxUixCSvvbg1x6sh"
377392
address = "2MuhcG52uHPknxDgmGPsV18jSHFBnnRgjPg"

0 commit comments

Comments
 (0)