@@ -5750,16 +5750,42 @@ void CWallet::AddActiveScriptPubKeyMan(uint256 id, bool internal)
5750
5750
5751
5751
void CWallet::LoadActiveScriptPubKeyMan (uint256 id, bool internal)
5752
5752
{
5753
+ // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
5754
+ // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
5755
+ Assert (IsWalletFlagSet (WALLET_FLAG_DESCRIPTORS));
5756
+
5753
5757
WalletLogPrintf (" Setting spkMan to active: id = %s, type = %d, internal = %d\n " , id.ToString (), static_cast <int >(OutputType::LEGACY), static_cast <int >(internal));
5754
5758
auto & spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
5759
+ auto & spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
5755
5760
auto spk_man = m_spk_managers.at (id).get ();
5756
5761
spk_man->SetInternal (internal);
5757
5762
spk_mans = spk_man;
5758
5763
5764
+ if (spk_mans_other == spk_man) {
5765
+ spk_mans_other = nullptr ;
5766
+ }
5767
+
5759
5768
NotifyCanGetAddressesChanged ();
5760
5769
5761
5770
}
5762
5771
5772
+ void CWallet::DeactivateScriptPubKeyMan (uint256 id, bool internal)
5773
+ {
5774
+ auto spk_man = GetScriptPubKeyMan (internal);
5775
+ if (spk_man != nullptr && spk_man->GetID () == id) {
5776
+ WalletLogPrintf (" Deactivate spkMan: id = %s, type = %d, internal = %d\n " , id.ToString (), static_cast <int >(OutputType::LEGACY), static_cast <int >(internal));
5777
+ WalletBatch batch (GetDatabase ());
5778
+ if (!batch.EraseActiveScriptPubKeyMan (internal)) {
5779
+ throw std::runtime_error (std::string (__func__) + " : erasing active ScriptPubKeyMan id failed" );
5780
+ }
5781
+
5782
+ auto & spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
5783
+ spk_mans = nullptr ;
5784
+ }
5785
+
5786
+ NotifyCanGetAddressesChanged ();
5787
+ }
5788
+
5763
5789
bool CWallet::IsLegacy () const
5764
5790
{
5765
5791
if (m_internal_spk_managers == nullptr ) return false ;
@@ -5788,52 +5814,34 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
5788
5814
}
5789
5815
5790
5816
LOCK (cs_wallet);
5791
- auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan (*this , desc));
5792
-
5793
- // If we already have this descriptor, remove it from the maps but add the existing cache to desc
5794
- auto old_spk_man = GetDescriptorScriptPubKeyMan (desc);
5795
- if (old_spk_man) {
5817
+ auto spk_man = GetDescriptorScriptPubKeyMan (desc);
5818
+ if (spk_man) {
5796
5819
WalletLogPrintf (" Update existing descriptor: %s\n " , desc.descriptor ->ToString ());
5820
+ spk_man->UpdateWalletDescriptor (desc);
5821
+ } else {
5822
+ auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan (*this , desc));
5823
+ spk_man = new_spk_man.get ();
5797
5824
5798
- {
5799
- LOCK (old_spk_man->cs_desc_man );
5800
- new_spk_man->SetCache (old_spk_man->GetWalletDescriptor ().cache );
5801
- }
5802
-
5803
- // Remove from maps of active spkMans
5804
- auto old_spk_man_id = old_spk_man->GetID ();
5805
- for (bool internal : {false , true }) {
5806
- { // only one OutputType - LEGACY
5807
- auto active_spk_man = GetScriptPubKeyMan (internal);
5808
- if (active_spk_man && active_spk_man->GetID () == old_spk_man_id) {
5809
- if (internal) {
5810
- m_internal_spk_managers = nullptr ;
5811
- } else {
5812
- m_external_spk_managers = nullptr ;
5813
- }
5814
- break ;
5815
- }
5816
- }
5817
- }
5818
- m_spk_managers.erase (old_spk_man_id);
5825
+ // Save the descriptor to memory
5826
+ m_spk_managers[new_spk_man->GetID ()] = std::move (new_spk_man);
5819
5827
}
5820
5828
5821
5829
// Add the private keys to the descriptor
5822
5830
for (const auto & entry : signing_provider.keys ) {
5823
5831
const CKey& key = entry.second ;
5824
- new_spk_man ->AddDescriptorKey (key, key.GetPubKey ());
5832
+ spk_man ->AddDescriptorKey (key, key.GetPubKey ());
5825
5833
}
5826
5834
5827
5835
// Top up key pool, the manager will generate new scriptPubKeys internally
5828
- if (!new_spk_man ->TopUp ()) {
5836
+ if (!spk_man ->TopUp ()) {
5829
5837
WalletLogPrintf (" Could not top up scriptPubKeys\n " );
5830
5838
return nullptr ;
5831
5839
}
5832
5840
5833
5841
// Apply the label if necessary
5834
5842
// Note: we disable labels for ranged descriptors
5835
5843
if (!desc.descriptor ->IsRange ()) {
5836
- auto script_pub_keys = new_spk_man ->GetScriptPubKeys ();
5844
+ auto script_pub_keys = spk_man ->GetScriptPubKeys ();
5837
5845
if (script_pub_keys.empty ()) {
5838
5846
WalletLogPrintf (" Could not generate scriptPubKeys (cache is empty)\n " );
5839
5847
return nullptr ;
@@ -5845,12 +5853,8 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
5845
5853
}
5846
5854
}
5847
5855
5848
- // Save the descriptor to memory
5849
- auto ret = new_spk_man.get ();
5850
- m_spk_managers[new_spk_man->GetID ()] = std::move (new_spk_man);
5851
-
5852
5856
// Save the descriptor to DB
5853
- ret ->WriteDescriptor ();
5857
+ spk_man ->WriteDescriptor ();
5854
5858
5855
- return ret ;
5859
+ return spk_man ;
5856
5860
}
0 commit comments