1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <wallet/wallet.h>
7 
8 #include <chain.h>
9 #include <consensus/consensus.h>
10 #include <consensus/validation.h>
11 #include <external_signer.h>
12 #include <fs.h>
13 #include <interfaces/chain.h>
14 #include <interfaces/wallet.h>
15 #include <key.h>
16 #include <key_io.h>
17 #include <outputtype.h>
18 #include <policy/fees.h>
19 #include <policy/policy.h>
20 #include <primitives/block.h>
21 #include <primitives/transaction.h>
22 #include <psbt.h>
23 #include <script/descriptor.h>
24 #include <script/script.h>
25 #include <script/signingprovider.h>
26 #include <txmempool.h>
27 #include <util/bip32.h>
28 #include <util/check.h>
29 #include <util/error.h>
30 #include <util/fees.h>
31 #include <util/moneystr.h>
32 #include <util/rbf.h>
33 #include <util/string.h>
34 #include <util/translation.h>
35 #include <wallet/coincontrol.h>
36 #include <wallet/fees.h>
37 #include <wallet/external_signer_scriptpubkeyman.h>
38 
39 #include <univalue.h>
40 
41 #include <algorithm>
42 #include <assert.h>
43 #include <optional>
44 
45 #include <boost/algorithm/string/replace.hpp>
46 
47 using interfaces::FoundBlock;
48 
49 const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
50     {WALLET_FLAG_AVOID_REUSE,
51         "You need to rescan the blockchain in order to correctly mark used "
52         "destinations in the past. Until this is done, some destinations may "
53         "be considered unused, even if the opposite is the case."
54     },
55 };
56 
57 RecursiveMutex cs_wallets;
58 static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
59 static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
60 
AddWalletSetting(interfaces::Chain & chain,const std::string & wallet_name)61 bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
62 {
63     util::SettingsValue setting_value = chain.getRwSetting("wallet");
64     if (!setting_value.isArray()) setting_value.setArray();
65     for (const util::SettingsValue& value : setting_value.getValues()) {
66         if (value.isStr() && value.get_str() == wallet_name) return true;
67     }
68     setting_value.push_back(wallet_name);
69     return chain.updateRwSetting("wallet", setting_value);
70 }
71 
RemoveWalletSetting(interfaces::Chain & chain,const std::string & wallet_name)72 bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
73 {
74     util::SettingsValue setting_value = chain.getRwSetting("wallet");
75     if (!setting_value.isArray()) return true;
76     util::SettingsValue new_value(util::SettingsValue::VARR);
77     for (const util::SettingsValue& value : setting_value.getValues()) {
78         if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
79     }
80     if (new_value.size() == setting_value.size()) return true;
81     return chain.updateRwSetting("wallet", new_value);
82 }
83 
UpdateWalletSetting(interfaces::Chain & chain,const std::string & wallet_name,std::optional<bool> load_on_startup,std::vector<bilingual_str> & warnings)84 static void UpdateWalletSetting(interfaces::Chain& chain,
85                                 const std::string& wallet_name,
86                                 std::optional<bool> load_on_startup,
87                                 std::vector<bilingual_str>& warnings)
88 {
89     if (!load_on_startup) return;
90     if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
91         warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
92     } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
93         warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
94     }
95 }
96 
AddWallet(const std::shared_ptr<CWallet> & wallet)97 bool AddWallet(const std::shared_ptr<CWallet>& wallet)
98 {
99     LOCK(cs_wallets);
100     assert(wallet);
101     std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
102     if (i != vpwallets.end()) return false;
103     vpwallets.push_back(wallet);
104     wallet->ConnectScriptPubKeyManNotifiers();
105     wallet->NotifyCanGetAddressesChanged();
106     return true;
107 }
108 
RemoveWallet(const std::shared_ptr<CWallet> & wallet,std::optional<bool> load_on_start,std::vector<bilingual_str> & warnings)109 bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
110 {
111     assert(wallet);
112 
113     interfaces::Chain& chain = wallet->chain();
114     std::string name = wallet->GetName();
115 
116     // Unregister with the validation interface which also drops shared ponters.
117     wallet->m_chain_notifications_handler.reset();
118     LOCK(cs_wallets);
119     std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
120     if (i == vpwallets.end()) return false;
121     vpwallets.erase(i);
122 
123     // Write the wallet setting
124     UpdateWalletSetting(chain, name, load_on_start, warnings);
125 
126     return true;
127 }
128 
RemoveWallet(const std::shared_ptr<CWallet> & wallet,std::optional<bool> load_on_start)129 bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start)
130 {
131     std::vector<bilingual_str> warnings;
132     return RemoveWallet(wallet, load_on_start, warnings);
133 }
134 
GetWallets()135 std::vector<std::shared_ptr<CWallet>> GetWallets()
136 {
137     LOCK(cs_wallets);
138     return vpwallets;
139 }
140 
GetWallet(const std::string & name)141 std::shared_ptr<CWallet> GetWallet(const std::string& name)
142 {
143     LOCK(cs_wallets);
144     for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
145         if (wallet->GetName() == name) return wallet;
146     }
147     return nullptr;
148 }
149 
HandleLoadWallet(LoadWalletFn load_wallet)150 std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet)
151 {
152     LOCK(cs_wallets);
153     auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
154     return interfaces::MakeHandler([it] { LOCK(cs_wallets); g_load_wallet_fns.erase(it); });
155 }
156 
157 static Mutex g_loading_wallet_mutex;
158 static Mutex g_wallet_release_mutex;
159 static std::condition_variable g_wallet_release_cv;
160 static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
161 static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
162 
163 // Custom deleter for shared_ptr<CWallet>.
ReleaseWallet(CWallet * wallet)164 static void ReleaseWallet(CWallet* wallet)
165 {
166     const std::string name = wallet->GetName();
167     wallet->WalletLogPrintf("Releasing wallet\n");
168     wallet->Flush();
169     delete wallet;
170     // Wallet is now released, notify UnloadWallet, if any.
171     {
172         LOCK(g_wallet_release_mutex);
173         if (g_unloading_wallet_set.erase(name) == 0) {
174             // UnloadWallet was not called for this wallet, all done.
175             return;
176         }
177     }
178     g_wallet_release_cv.notify_all();
179 }
180 
UnloadWallet(std::shared_ptr<CWallet> && wallet)181 void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
182 {
183     // Mark wallet for unloading.
184     const std::string name = wallet->GetName();
185     {
186         LOCK(g_wallet_release_mutex);
187         auto it = g_unloading_wallet_set.insert(name);
188         assert(it.second);
189     }
190     // The wallet can be in use so it's not possible to explicitly unload here.
191     // Notify the unload intent so that all remaining shared pointers are
192     // released.
193     wallet->NotifyUnload();
194 
195     // Time to ditch our shared_ptr and wait for ReleaseWallet call.
196     wallet.reset();
197     {
198         WAIT_LOCK(g_wallet_release_mutex, lock);
199         while (g_unloading_wallet_set.count(name) == 1) {
200             g_wallet_release_cv.wait(lock);
201         }
202     }
203 }
204 
205 namespace {
LoadWalletInternal(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)206 std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
207 {
208     try {
209         std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
210         if (!database) {
211             error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
212             return nullptr;
213         }
214 
215         chain.initMessage(_("Loading wallet…").translated);
216         std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, name, std::move(database), options.create_flags, error, warnings);
217         if (!wallet) {
218             error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
219             status = DatabaseStatus::FAILED_LOAD;
220             return nullptr;
221         }
222         AddWallet(wallet);
223         wallet->postInitProcess();
224 
225         // Write the wallet setting
226         UpdateWalletSetting(chain, name, load_on_start, warnings);
227 
228         return wallet;
229     } catch (const std::runtime_error& e) {
230         error = Untranslated(e.what());
231         status = DatabaseStatus::FAILED_LOAD;
232         return nullptr;
233     }
234 }
235 } // namespace
236 
LoadWallet(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)237 std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
238 {
239     auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
240     if (!result.second) {
241         error = Untranslated("Wallet already loading.");
242         status = DatabaseStatus::FAILED_LOAD;
243         return nullptr;
244     }
245     auto wallet = LoadWalletInternal(chain, name, load_on_start, options, status, error, warnings);
246     WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
247     return wallet;
248 }
249 
CreateWallet(interfaces::Chain & chain,const std::string & name,std::optional<bool> load_on_start,DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error,std::vector<bilingual_str> & warnings)250 std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
251 {
252     uint64_t wallet_creation_flags = options.create_flags;
253     const SecureString& passphrase = options.create_passphrase;
254 
255     if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE;
256 
257     // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
258     bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
259 
260     // Born encrypted wallets need to be created blank first.
261     if (!passphrase.empty()) {
262         wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
263     }
264 
265     // Private keys must be disabled for an external signer wallet
266     if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
267         error = Untranslated("Private keys must be disabled when using an external signer");
268         status = DatabaseStatus::FAILED_CREATE;
269         return nullptr;
270     }
271 
272     // Descriptor support must be enabled for an external signer wallet
273     if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) {
274         error = Untranslated("Descriptor support must be enabled when using an external signer");
275         status = DatabaseStatus::FAILED_CREATE;
276         return nullptr;
277     }
278 
279     // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
280     std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
281     if (!database) {
282         error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
283         status = DatabaseStatus::FAILED_VERIFY;
284         return nullptr;
285     }
286 
287     // Do not allow a passphrase when private keys are disabled
288     if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
289         error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
290         status = DatabaseStatus::FAILED_CREATE;
291         return nullptr;
292     }
293 
294     // Make the wallet
295     chain.initMessage(_("Loading wallet…").translated);
296     std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, name, std::move(database), wallet_creation_flags, error, warnings);
297     if (!wallet) {
298         error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
299         status = DatabaseStatus::FAILED_CREATE;
300         return nullptr;
301     }
302 
303     // Encrypt the wallet
304     if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
305         if (!wallet->EncryptWallet(passphrase)) {
306             error = Untranslated("Error: Wallet created but failed to encrypt.");
307             status = DatabaseStatus::FAILED_ENCRYPT;
308             return nullptr;
309         }
310         if (!create_blank) {
311             // Unlock the wallet
312             if (!wallet->Unlock(passphrase)) {
313                 error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
314                 status = DatabaseStatus::FAILED_ENCRYPT;
315                 return nullptr;
316             }
317 
318             // Set a seed for the wallet
319             {
320                 LOCK(wallet->cs_wallet);
321                 if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
322                     wallet->SetupDescriptorScriptPubKeyMans();
323                 } else {
324                     for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
325                         if (!spk_man->SetupGeneration()) {
326                             error = Untranslated("Unable to generate initial keys");
327                             status = DatabaseStatus::FAILED_CREATE;
328                             return nullptr;
329                         }
330                     }
331                 }
332             }
333 
334             // Relock the wallet
335             wallet->Lock();
336         }
337     }
338     AddWallet(wallet);
339     wallet->postInitProcess();
340 
341     // Write the wallet settings
342     UpdateWalletSetting(chain, name, load_on_start, warnings);
343 
344     status = DatabaseStatus::SUCCESS;
345     return wallet;
346 }
347 
348 /** @defgroup mapWallet
349  *
350  * @{
351  */
352 
GetWalletTx(const uint256 & hash) const353 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
354 {
355     AssertLockHeld(cs_wallet);
356     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
357     if (it == mapWallet.end())
358         return nullptr;
359     return &(it->second);
360 }
361 
UpgradeKeyMetadata()362 void CWallet::UpgradeKeyMetadata()
363 {
364     if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
365         return;
366     }
367 
368     auto spk_man = GetLegacyScriptPubKeyMan();
369     if (!spk_man) {
370         return;
371     }
372 
373     spk_man->UpgradeKeyMetadata();
374     SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
375 }
376 
UpgradeDescriptorCache()377 void CWallet::UpgradeDescriptorCache()
378 {
379     if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) || IsLocked() || IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
380         return;
381     }
382 
383     for (ScriptPubKeyMan* spkm : GetAllScriptPubKeyMans()) {
384         DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
385         desc_spkm->UpgradeDescriptorCache();
386     }
387     SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED);
388 }
389 
Unlock(const SecureString & strWalletPassphrase,bool accept_no_keys)390 bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
391 {
392     CCrypter crypter;
393     CKeyingMaterial _vMasterKey;
394 
395     {
396         LOCK(cs_wallet);
397         for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
398         {
399             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
400                 return false;
401             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
402                 continue; // try another master key
403             if (Unlock(_vMasterKey, accept_no_keys)) {
404                 // Now that we've unlocked, upgrade the key metadata
405                 UpgradeKeyMetadata();
406                 // Now that we've unlocked, upgrade the descriptor cache
407                 UpgradeDescriptorCache();
408                 return true;
409             }
410         }
411     }
412     return false;
413 }
414 
ChangeWalletPassphrase(const SecureString & strOldWalletPassphrase,const SecureString & strNewWalletPassphrase)415 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
416 {
417     bool fWasLocked = IsLocked();
418 
419     {
420         LOCK(cs_wallet);
421         Lock();
422 
423         CCrypter crypter;
424         CKeyingMaterial _vMasterKey;
425         for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
426         {
427             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
428                 return false;
429             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
430                 return false;
431             if (Unlock(_vMasterKey))
432             {
433                 int64_t nStartTime = GetTimeMillis();
434                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
435                 pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
436 
437                 nStartTime = GetTimeMillis();
438                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
439                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
440 
441                 if (pMasterKey.second.nDeriveIterations < 25000)
442                     pMasterKey.second.nDeriveIterations = 25000;
443 
444                 WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
445 
446                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
447                     return false;
448                 if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
449                     return false;
450                 WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second);
451                 if (fWasLocked)
452                     Lock();
453                 return true;
454             }
455         }
456     }
457 
458     return false;
459 }
460 
chainStateFlushed(const CBlockLocator & loc)461 void CWallet::chainStateFlushed(const CBlockLocator& loc)
462 {
463     WalletBatch batch(GetDatabase());
464     batch.WriteBestBlock(loc);
465 }
466 
SetMinVersion(enum WalletFeature nVersion,WalletBatch * batch_in)467 void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
468 {
469     LOCK(cs_wallet);
470     if (nWalletVersion >= nVersion)
471         return;
472     nWalletVersion = nVersion;
473 
474     {
475         WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase());
476         if (nWalletVersion > 40000)
477             batch->WriteMinVersion(nWalletVersion);
478         if (!batch_in)
479             delete batch;
480     }
481 }
482 
GetConflicts(const uint256 & txid) const483 std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
484 {
485     std::set<uint256> result;
486     AssertLockHeld(cs_wallet);
487 
488     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
489     if (it == mapWallet.end())
490         return result;
491     const CWalletTx& wtx = it->second;
492 
493     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
494 
495     for (const CTxIn& txin : wtx.tx->vin)
496     {
497         if (mapTxSpends.count(txin.prevout) <= 1)
498             continue;  // No conflict if zero or one spends
499         range = mapTxSpends.equal_range(txin.prevout);
500         for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
501             result.insert(_it->second);
502     }
503     return result;
504 }
505 
HasWalletSpend(const uint256 & txid) const506 bool CWallet::HasWalletSpend(const uint256& txid) const
507 {
508     AssertLockHeld(cs_wallet);
509     auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
510     return (iter != mapTxSpends.end() && iter->first.hash == txid);
511 }
512 
Flush()513 void CWallet::Flush()
514 {
515     GetDatabase().Flush();
516 }
517 
Close()518 void CWallet::Close()
519 {
520     GetDatabase().Close();
521 }
522 
SyncMetaData(std::pair<TxSpends::iterator,TxSpends::iterator> range)523 void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
524 {
525     // We want all the wallet transactions in range to have the same metadata as
526     // the oldest (smallest nOrderPos).
527     // So: find smallest nOrderPos:
528 
529     int nMinOrderPos = std::numeric_limits<int>::max();
530     const CWalletTx* copyFrom = nullptr;
531     for (TxSpends::iterator it = range.first; it != range.second; ++it) {
532         const CWalletTx* wtx = &mapWallet.at(it->second);
533         if (wtx->nOrderPos < nMinOrderPos) {
534             nMinOrderPos = wtx->nOrderPos;
535             copyFrom = wtx;
536         }
537     }
538 
539     if (!copyFrom) {
540         return;
541     }
542 
543     // Now copy data from copyFrom to rest:
544     for (TxSpends::iterator it = range.first; it != range.second; ++it)
545     {
546         const uint256& hash = it->second;
547         CWalletTx* copyTo = &mapWallet.at(hash);
548         if (copyFrom == copyTo) continue;
549         assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
550         if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
551         copyTo->mapValue = copyFrom->mapValue;
552         copyTo->vOrderForm = copyFrom->vOrderForm;
553         // fTimeReceivedIsTxTime not copied on purpose
554         // nTimeReceived not copied on purpose
555         copyTo->nTimeSmart = copyFrom->nTimeSmart;
556         copyTo->fFromMe = copyFrom->fFromMe;
557         // nOrderPos not copied on purpose
558         // cached members not copied on purpose
559     }
560 }
561 
562 /**
563  * Outpoint is spent if any non-conflicted transaction
564  * spends it:
565  */
IsSpent(const uint256 & hash,unsigned int n) const566 bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
567 {
568     const COutPoint outpoint(hash, n);
569     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
570     range = mapTxSpends.equal_range(outpoint);
571 
572     for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
573     {
574         const uint256& wtxid = it->second;
575         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
576         if (mit != mapWallet.end()) {
577             int depth = mit->second.GetDepthInMainChain();
578             if (depth > 0  || (depth == 0 && !mit->second.isAbandoned()))
579                 return true; // Spent
580         }
581     }
582     return false;
583 }
584 
AddToSpends(const COutPoint & outpoint,const uint256 & wtxid)585 void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
586 {
587     mapTxSpends.insert(std::make_pair(outpoint, wtxid));
588 
589     setLockedCoins.erase(outpoint);
590 
591     std::pair<TxSpends::iterator, TxSpends::iterator> range;
592     range = mapTxSpends.equal_range(outpoint);
593     SyncMetaData(range);
594 }
595 
596 
AddToSpends(const uint256 & wtxid)597 void CWallet::AddToSpends(const uint256& wtxid)
598 {
599     auto it = mapWallet.find(wtxid);
600     assert(it != mapWallet.end());
601     const CWalletTx& thisTx = it->second;
602     if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
603         return;
604 
605     for (const CTxIn& txin : thisTx.tx->vin)
606         AddToSpends(txin.prevout, wtxid);
607 }
608 
EncryptWallet(const SecureString & strWalletPassphrase)609 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
610 {
611     if (IsCrypted())
612         return false;
613 
614     CKeyingMaterial _vMasterKey;
615 
616     _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
617     GetStrongRandBytes(_vMasterKey.data(), WALLET_CRYPTO_KEY_SIZE);
618 
619     CMasterKey kMasterKey;
620 
621     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
622     GetStrongRandBytes(kMasterKey.vchSalt.data(), WALLET_CRYPTO_SALT_SIZE);
623 
624     CCrypter crypter;
625     int64_t nStartTime = GetTimeMillis();
626     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
627     kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
628 
629     nStartTime = GetTimeMillis();
630     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
631     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
632 
633     if (kMasterKey.nDeriveIterations < 25000)
634         kMasterKey.nDeriveIterations = 25000;
635 
636     WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
637 
638     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
639         return false;
640     if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
641         return false;
642 
643     {
644         LOCK(cs_wallet);
645         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
646         WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
647         if (!encrypted_batch->TxnBegin()) {
648             delete encrypted_batch;
649             encrypted_batch = nullptr;
650             return false;
651         }
652         encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
653 
654         for (const auto& spk_man_pair : m_spk_managers) {
655             auto spk_man = spk_man_pair.second.get();
656             if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
657                 encrypted_batch->TxnAbort();
658                 delete encrypted_batch;
659                 encrypted_batch = nullptr;
660                 // We now probably have half of our keys encrypted in memory, and half not...
661                 // die and let the user reload the unencrypted wallet.
662                 assert(false);
663             }
664         }
665 
666         // Encryption was introduced in version 0.4.0
667         SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
668 
669         if (!encrypted_batch->TxnCommit()) {
670             delete encrypted_batch;
671             encrypted_batch = nullptr;
672             // We now have keys encrypted in memory, but not on disk...
673             // die to avoid confusion and let the user reload the unencrypted wallet.
674             assert(false);
675         }
676 
677         delete encrypted_batch;
678         encrypted_batch = nullptr;
679 
680         Lock();
681         Unlock(strWalletPassphrase);
682 
683         // If we are using descriptors, make new descriptors with a new seed
684         if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
685             SetupDescriptorScriptPubKeyMans();
686         } else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
687             // if we are using HD, replace the HD seed with a new one
688             if (spk_man->IsHDEnabled()) {
689                 if (!spk_man->SetupGeneration(true)) {
690                     return false;
691                 }
692             }
693         }
694         Lock();
695 
696         // Need to completely rewrite the wallet file; if we don't, bdb might keep
697         // bits of the unencrypted private key in slack space in the database file.
698         GetDatabase().Rewrite();
699 
700         // BDB seems to have a bad habit of writing old data into
701         // slack space in .dat files; that is bad if the old data is
702         // unencrypted private keys. So:
703         GetDatabase().ReloadDbEnv();
704 
705     }
706     NotifyStatusChanged(this);
707 
708     return true;
709 }
710 
ReorderTransactions()711 DBErrors CWallet::ReorderTransactions()
712 {
713     LOCK(cs_wallet);
714     WalletBatch batch(GetDatabase());
715 
716     // Old wallets didn't have any defined order for transactions
717     // Probably a bad idea to change the output of this
718 
719     // First: get all CWalletTx into a sorted-by-time multimap.
720     typedef std::multimap<int64_t, CWalletTx*> TxItems;
721     TxItems txByTime;
722 
723     for (auto& entry : mapWallet)
724     {
725         CWalletTx* wtx = &entry.second;
726         txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
727     }
728 
729     nOrderPosNext = 0;
730     std::vector<int64_t> nOrderPosOffsets;
731     for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
732     {
733         CWalletTx *const pwtx = (*it).second;
734         int64_t& nOrderPos = pwtx->nOrderPos;
735 
736         if (nOrderPos == -1)
737         {
738             nOrderPos = nOrderPosNext++;
739             nOrderPosOffsets.push_back(nOrderPos);
740 
741             if (!batch.WriteTx(*pwtx))
742                 return DBErrors::LOAD_FAIL;
743         }
744         else
745         {
746             int64_t nOrderPosOff = 0;
747             for (const int64_t& nOffsetStart : nOrderPosOffsets)
748             {
749                 if (nOrderPos >= nOffsetStart)
750                     ++nOrderPosOff;
751             }
752             nOrderPos += nOrderPosOff;
753             nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
754 
755             if (!nOrderPosOff)
756                 continue;
757 
758             // Since we're changing the order, write it back
759             if (!batch.WriteTx(*pwtx))
760                 return DBErrors::LOAD_FAIL;
761         }
762     }
763     batch.WriteOrderPosNext(nOrderPosNext);
764 
765     return DBErrors::LOAD_OK;
766 }
767 
IncOrderPosNext(WalletBatch * batch)768 int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
769 {
770     AssertLockHeld(cs_wallet);
771     int64_t nRet = nOrderPosNext++;
772     if (batch) {
773         batch->WriteOrderPosNext(nOrderPosNext);
774     } else {
775         WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
776     }
777     return nRet;
778 }
779 
MarkDirty()780 void CWallet::MarkDirty()
781 {
782     {
783         LOCK(cs_wallet);
784         for (std::pair<const uint256, CWalletTx>& item : mapWallet)
785             item.second.MarkDirty();
786     }
787 }
788 
MarkReplaced(const uint256 & originalHash,const uint256 & newHash)789 bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
790 {
791     LOCK(cs_wallet);
792 
793     auto mi = mapWallet.find(originalHash);
794 
795     // There is a bug if MarkReplaced is not called on an existing wallet transaction.
796     assert(mi != mapWallet.end());
797 
798     CWalletTx& wtx = (*mi).second;
799 
800     // Ensure for now that we're not overwriting data
801     assert(wtx.mapValue.count("replaced_by_txid") == 0);
802 
803     wtx.mapValue["replaced_by_txid"] = newHash.ToString();
804 
805     // Refresh mempool status without waiting for transactionRemovedFromMempool
806     // notification so the wallet is in an internally consistent state and
807     // immediately knows the old transaction should not be considered trusted
808     // and is eligible to be abandoned
809     wtx.fInMempool = chain().isInMempool(originalHash);
810 
811     WalletBatch batch(GetDatabase());
812 
813     bool success = true;
814     if (!batch.WriteTx(wtx)) {
815         WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
816         success = false;
817     }
818 
819     NotifyTransactionChanged(originalHash, CT_UPDATED);
820 
821     return success;
822 }
823 
SetSpentKeyState(WalletBatch & batch,const uint256 & hash,unsigned int n,bool used,std::set<CTxDestination> & tx_destinations)824 void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
825 {
826     AssertLockHeld(cs_wallet);
827     const CWalletTx* srctx = GetWalletTx(hash);
828     if (!srctx) return;
829 
830     CTxDestination dst;
831     if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
832         if (IsMine(dst)) {
833             if (used != IsAddressUsed(dst)) {
834                 if (used) {
835                     tx_destinations.insert(dst);
836                 }
837                 SetAddressUsed(batch, dst, used);
838             }
839         }
840     }
841 }
842 
IsSpentKey(const uint256 & hash,unsigned int n) const843 bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
844 {
845     AssertLockHeld(cs_wallet);
846     const CWalletTx* srctx = GetWalletTx(hash);
847     if (srctx) {
848         assert(srctx->tx->vout.size() > n);
849         CTxDestination dest;
850         if (!ExtractDestination(srctx->tx->vout[n].scriptPubKey, dest)) {
851             return false;
852         }
853         if (IsAddressUsed(dest)) {
854             return true;
855         }
856         if (IsLegacy()) {
857             LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
858             assert(spk_man != nullptr);
859             for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
860                 WitnessV0KeyHash wpkh_dest(keyid);
861                 if (IsAddressUsed(wpkh_dest)) {
862                     return true;
863                 }
864                 ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
865                 if (IsAddressUsed(sh_wpkh_dest)) {
866                     return true;
867                 }
868                 PKHash pkh_dest(keyid);
869                 if (IsAddressUsed(pkh_dest)) {
870                     return true;
871                 }
872             }
873         }
874     }
875     return false;
876 }
877 
AddToWallet(CTransactionRef tx,const CWalletTx::Confirmation & confirm,const UpdateWalletTxFn & update_wtx,bool fFlushOnClose)878 CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose)
879 {
880     LOCK(cs_wallet);
881 
882     WalletBatch batch(GetDatabase(), fFlushOnClose);
883 
884     uint256 hash = tx->GetHash();
885 
886     if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
887         // Mark used destinations
888         std::set<CTxDestination> tx_destinations;
889 
890         for (const CTxIn& txin : tx->vin) {
891             const COutPoint& op = txin.prevout;
892             SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
893         }
894 
895         MarkDestinationsDirty(tx_destinations);
896     }
897 
898     // Inserts only if not already there, returns tx inserted or tx found
899     auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, tx));
900     CWalletTx& wtx = (*ret.first).second;
901     bool fInsertedNew = ret.second;
902     bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
903     if (fInsertedNew) {
904         wtx.m_confirm = confirm;
905         wtx.nTimeReceived = chain().getAdjustedTime();
906         wtx.nOrderPos = IncOrderPosNext(&batch);
907         wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
908         wtx.nTimeSmart = ComputeTimeSmart(wtx);
909         AddToSpends(hash);
910     }
911 
912     if (!fInsertedNew)
913     {
914         if (confirm.status != wtx.m_confirm.status) {
915             wtx.m_confirm.status = confirm.status;
916             wtx.m_confirm.nIndex = confirm.nIndex;
917             wtx.m_confirm.hashBlock = confirm.hashBlock;
918             wtx.m_confirm.block_height = confirm.block_height;
919             fUpdated = true;
920         } else {
921             assert(wtx.m_confirm.nIndex == confirm.nIndex);
922             assert(wtx.m_confirm.hashBlock == confirm.hashBlock);
923             assert(wtx.m_confirm.block_height == confirm.block_height);
924         }
925         // If we have a witness-stripped version of this transaction, and we
926         // see a new version with a witness, then we must be upgrading a pre-segwit
927         // wallet.  Store the new version of the transaction with the witness,
928         // as the stripped-version must be invalid.
929         // TODO: Store all versions of the transaction, instead of just one.
930         if (tx->HasWitness() && !wtx.tx->HasWitness()) {
931             wtx.SetTx(tx);
932             fUpdated = true;
933         }
934     }
935 
936     //// debug print
937     WalletLogPrintf("AddToWallet %s  %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
938 
939     // Write to disk
940     if (fInsertedNew || fUpdated)
941         if (!batch.WriteTx(wtx))
942             return nullptr;
943 
944     // Break debit/credit balance caches:
945     wtx.MarkDirty();
946 
947     // Notify UI of new or updated transaction
948     NotifyTransactionChanged(hash, fInsertedNew ? CT_NEW : CT_UPDATED);
949 
950 #if HAVE_SYSTEM
951     // notify an external script when a wallet transaction comes in or is updated
952     std::string strCmd = gArgs.GetArg("-walletnotify", "");
953 
954     if (!strCmd.empty())
955     {
956         boost::replace_all(strCmd, "%s", hash.GetHex());
957         if (confirm.status == CWalletTx::Status::CONFIRMED)
958         {
959             boost::replace_all(strCmd, "%b", confirm.hashBlock.GetHex());
960             boost::replace_all(strCmd, "%h", ToString(confirm.block_height));
961         } else {
962             boost::replace_all(strCmd, "%b", "unconfirmed");
963             boost::replace_all(strCmd, "%h", "-1");
964         }
965 #ifndef WIN32
966         // Substituting the wallet name isn't currently supported on windows
967         // because windows shell escaping has not been implemented yet:
968         // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
969         // A few ways it could be implemented in the future are described in:
970         // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
971         boost::replace_all(strCmd, "%w", ShellEscape(GetName()));
972 #endif
973         std::thread t(runCommand, strCmd);
974         t.detach(); // thread runs free
975     }
976 #endif
977 
978     return &wtx;
979 }
980 
LoadToWallet(const uint256 & hash,const UpdateWalletTxFn & fill_wtx)981 bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx)
982 {
983     const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, nullptr));
984     CWalletTx& wtx = ins.first->second;
985     if (!fill_wtx(wtx, ins.second)) {
986         return false;
987     }
988     // If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn.
989     if (HaveChain()) {
990         bool active;
991         int height;
992         if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
993             // Update cached block height variable since it not stored in the
994             // serialized transaction.
995             wtx.m_confirm.block_height = height;
996         } else if (wtx.isConflicted() || wtx.isConfirmed()) {
997             // If tx block (or conflicting block) was reorged out of chain
998             // while the wallet was shutdown, change tx status to UNCONFIRMED
999             // and reset block height, hash, and index. ABANDONED tx don't have
1000             // associated blocks and don't need to be updated. The case where a
1001             // transaction was reorged out while online and then reconfirmed
1002             // while offline is covered by the rescan logic.
1003             wtx.setUnconfirmed();
1004             wtx.m_confirm.hashBlock = uint256();
1005             wtx.m_confirm.block_height = 0;
1006             wtx.m_confirm.nIndex = 0;
1007         }
1008     }
1009     if (/* insertion took place */ ins.second) {
1010         wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
1011     }
1012     AddToSpends(hash);
1013     for (const CTxIn& txin : wtx.tx->vin) {
1014         auto it = mapWallet.find(txin.prevout.hash);
1015         if (it != mapWallet.end()) {
1016             CWalletTx& prevtx = it->second;
1017             if (prevtx.isConflicted()) {
1018                 MarkConflicted(prevtx.m_confirm.hashBlock, prevtx.m_confirm.block_height, wtx.GetHash());
1019             }
1020         }
1021     }
1022     return true;
1023 }
1024 
AddToWalletIfInvolvingMe(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool fUpdate)1025 bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate)
1026 {
1027     const CTransaction& tx = *ptx;
1028     {
1029         AssertLockHeld(cs_wallet);
1030 
1031         if (!confirm.hashBlock.IsNull()) {
1032             for (const CTxIn& txin : tx.vin) {
1033                 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1034                 while (range.first != range.second) {
1035                     if (range.first->second != tx.GetHash()) {
1036                         WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), confirm.hashBlock.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
1037                         MarkConflicted(confirm.hashBlock, confirm.block_height, range.first->second);
1038                     }
1039                     range.first++;
1040                 }
1041             }
1042         }
1043 
1044         bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1045         if (fExisted && !fUpdate) return false;
1046         if (fExisted || IsMine(tx) || IsFromMe(tx))
1047         {
1048             /* Check if any keys in the wallet keypool that were supposed to be unused
1049              * have appeared in a new transaction. If so, remove those keys from the keypool.
1050              * This can happen when restoring an old wallet backup that does not contain
1051              * the mostly recently created transactions from newer versions of the wallet.
1052              */
1053 
1054             // loop though all outputs
1055             for (const CTxOut& txout: tx.vout) {
1056                 for (const auto& spk_man_pair : m_spk_managers) {
1057                     spk_man_pair.second->MarkUnusedAddresses(txout.scriptPubKey);
1058                 }
1059             }
1060 
1061             // Block disconnection override an abandoned tx as unconfirmed
1062             // which means user may have to call abandontransaction again
1063             return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false);
1064         }
1065     }
1066     return false;
1067 }
1068 
TransactionCanBeAbandoned(const uint256 & hashTx) const1069 bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
1070 {
1071     LOCK(cs_wallet);
1072     const CWalletTx* wtx = GetWalletTx(hashTx);
1073     return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
1074 }
1075 
MarkInputsDirty(const CTransactionRef & tx)1076 void CWallet::MarkInputsDirty(const CTransactionRef& tx)
1077 {
1078     for (const CTxIn& txin : tx->vin) {
1079         auto it = mapWallet.find(txin.prevout.hash);
1080         if (it != mapWallet.end()) {
1081             it->second.MarkDirty();
1082         }
1083     }
1084 }
1085 
AbandonTransaction(const uint256 & hashTx)1086 bool CWallet::AbandonTransaction(const uint256& hashTx)
1087 {
1088     LOCK(cs_wallet);
1089 
1090     WalletBatch batch(GetDatabase());
1091 
1092     std::set<uint256> todo;
1093     std::set<uint256> done;
1094 
1095     // Can't mark abandoned if confirmed or in mempool
1096     auto it = mapWallet.find(hashTx);
1097     assert(it != mapWallet.end());
1098     const CWalletTx& origtx = it->second;
1099     if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1100         return false;
1101     }
1102 
1103     todo.insert(hashTx);
1104 
1105     while (!todo.empty()) {
1106         uint256 now = *todo.begin();
1107         todo.erase(now);
1108         done.insert(now);
1109         auto it = mapWallet.find(now);
1110         assert(it != mapWallet.end());
1111         CWalletTx& wtx = it->second;
1112         int currentconfirm = wtx.GetDepthInMainChain();
1113         // If the orig tx was not in block, none of its spends can be
1114         assert(currentconfirm <= 0);
1115         // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
1116         if (currentconfirm == 0 && !wtx.isAbandoned()) {
1117             // If the orig tx was not in block/mempool, none of its spends can be in mempool
1118             assert(!wtx.InMempool());
1119             wtx.setAbandoned();
1120             wtx.MarkDirty();
1121             batch.WriteTx(wtx);
1122             NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
1123             // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
1124             TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1125             while (iter != mapTxSpends.end() && iter->first.hash == now) {
1126                 if (!done.count(iter->second)) {
1127                     todo.insert(iter->second);
1128                 }
1129                 iter++;
1130             }
1131             // If a transaction changes 'conflicted' state, that changes the balance
1132             // available of the outputs it spends. So force those to be recomputed
1133             MarkInputsDirty(wtx.tx);
1134         }
1135     }
1136 
1137     return true;
1138 }
1139 
MarkConflicted(const uint256 & hashBlock,int conflicting_height,const uint256 & hashTx)1140 void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1141 {
1142     LOCK(cs_wallet);
1143 
1144     int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1145     // If number of conflict confirms cannot be determined, this means
1146     // that the block is still unknown or not yet part of the main chain,
1147     // for example when loading the wallet during a reindex. Do nothing in that
1148     // case.
1149     if (conflictconfirms >= 0)
1150         return;
1151 
1152     // Do not flush the wallet here for performance reasons
1153     WalletBatch batch(GetDatabase(), false);
1154 
1155     std::set<uint256> todo;
1156     std::set<uint256> done;
1157 
1158     todo.insert(hashTx);
1159 
1160     while (!todo.empty()) {
1161         uint256 now = *todo.begin();
1162         todo.erase(now);
1163         done.insert(now);
1164         auto it = mapWallet.find(now);
1165         assert(it != mapWallet.end());
1166         CWalletTx& wtx = it->second;
1167         int currentconfirm = wtx.GetDepthInMainChain();
1168         if (conflictconfirms < currentconfirm) {
1169             // Block is 'more conflicted' than current confirm; update.
1170             // Mark transaction as conflicted with this block.
1171             wtx.m_confirm.nIndex = 0;
1172             wtx.m_confirm.hashBlock = hashBlock;
1173             wtx.m_confirm.block_height = conflicting_height;
1174             wtx.setConflicted();
1175             wtx.MarkDirty();
1176             batch.WriteTx(wtx);
1177             // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
1178             TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1179             while (iter != mapTxSpends.end() && iter->first.hash == now) {
1180                  if (!done.count(iter->second)) {
1181                      todo.insert(iter->second);
1182                  }
1183                  iter++;
1184             }
1185             // If a transaction changes 'conflicted' state, that changes the balance
1186             // available of the outputs it spends. So force those to be recomputed
1187             MarkInputsDirty(wtx.tx);
1188         }
1189     }
1190 }
1191 
SyncTransaction(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool update_tx)1192 void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx)
1193 {
1194     if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
1195         return; // Not one of ours
1196 
1197     // If a transaction changes 'conflicted' state, that changes the balance
1198     // available of the outputs it spends. So force those to be
1199     // recomputed, also:
1200     MarkInputsDirty(ptx);
1201 }
1202 
transactionAddedToMempool(const CTransactionRef & tx,uint64_t mempool_sequence)1203 void CWallet::transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {
1204     LOCK(cs_wallet);
1205     SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1206 
1207     auto it = mapWallet.find(tx->GetHash());
1208     if (it != mapWallet.end()) {
1209         it->second.fInMempool = true;
1210     }
1211 }
1212 
transactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason,uint64_t mempool_sequence)1213 void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {
1214     LOCK(cs_wallet);
1215     auto it = mapWallet.find(tx->GetHash());
1216     if (it != mapWallet.end()) {
1217         it->second.fInMempool = false;
1218     }
1219     // Handle transactions that were removed from the mempool because they
1220     // conflict with transactions in a newly connected block.
1221     if (reason == MemPoolRemovalReason::CONFLICT) {
1222         // Trigger external -walletnotify notifications for these transactions.
1223         // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
1224         //
1225         // 1. The transactionRemovedFromMempool callback does not currently
1226         //    provide the conflicting block's hash and height, and for backwards
1227         //    compatibility reasons it may not be not safe to store conflicted
1228         //    wallet transactions with a null block hash. See
1229         //    https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1230         // 2. For most of these transactions, the wallet's internal conflict
1231         //    detection in the blockConnected handler will subsequently call
1232         //    MarkConflicted and update them with CONFLICTED status anyway. This
1233         //    applies to any wallet transaction that has inputs spent in the
1234         //    block, or that has ancestors in the wallet with inputs spent by
1235         //    the block.
1236         // 3. Longstanding behavior since the sync implementation in
1237         //    https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1238         //    implementation before that was to mark these transactions
1239         //    unconfirmed rather than conflicted.
1240         //
1241         // Nothing described above should be seen as an unchangeable requirement
1242         // when improving this code in the future. The wallet's heuristics for
1243         // distinguishing between conflicted and unconfirmed transactions are
1244         // imperfect, and could be improved in general, see
1245         // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1246         SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1247     }
1248 }
1249 
blockConnected(const CBlock & block,int height)1250 void CWallet::blockConnected(const CBlock& block, int height)
1251 {
1252     const uint256& block_hash = block.GetHash();
1253     LOCK(cs_wallet);
1254 
1255     m_last_block_processed_height = height;
1256     m_last_block_processed = block_hash;
1257     for (size_t index = 0; index < block.vtx.size(); index++) {
1258         SyncTransaction(block.vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1259         transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */);
1260     }
1261 }
1262 
blockDisconnected(const CBlock & block,int height)1263 void CWallet::blockDisconnected(const CBlock& block, int height)
1264 {
1265     LOCK(cs_wallet);
1266 
1267     // At block disconnection, this will change an abandoned transaction to
1268     // be unconfirmed, whether or not the transaction is added back to the mempool.
1269     // User may have to call abandontransaction again. It may be addressed in the
1270     // future with a stickier abandoned state or even removing abandontransaction call.
1271     m_last_block_processed_height = height - 1;
1272     m_last_block_processed = block.hashPrevBlock;
1273     for (const CTransactionRef& ptx : block.vtx) {
1274         SyncTransaction(ptx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1275     }
1276 }
1277 
updatedBlockTip()1278 void CWallet::updatedBlockTip()
1279 {
1280     m_best_block_time = GetTime();
1281 }
1282 
1283 
BlockUntilSyncedToCurrentChain() const1284 void CWallet::BlockUntilSyncedToCurrentChain() const {
1285     AssertLockNotHeld(cs_wallet);
1286     // Skip the queue-draining stuff if we know we're caught up with
1287     // ::ChainActive().Tip(), otherwise put a callback in the validation interface queue and wait
1288     // for the queue to drain enough to execute it (indicating we are caught up
1289     // at least with the time we entered this function).
1290     uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1291     chain().waitForNotificationsIfTipChanged(last_block_hash);
1292 }
1293 
1294 // Note that this function doesn't distinguish between a 0-valued input,
1295 // and a not-"is mine" (according to the filter) input.
GetDebit(const CTxIn & txin,const isminefilter & filter) const1296 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1297 {
1298     {
1299         LOCK(cs_wallet);
1300         std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1301         if (mi != mapWallet.end())
1302         {
1303             const CWalletTx& prev = (*mi).second;
1304             if (txin.prevout.n < prev.tx->vout.size())
1305                 if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1306                     return prev.tx->vout[txin.prevout.n].nValue;
1307         }
1308     }
1309     return 0;
1310 }
1311 
IsMine(const CTxOut & txout) const1312 isminetype CWallet::IsMine(const CTxOut& txout) const
1313 {
1314     AssertLockHeld(cs_wallet);
1315     return IsMine(txout.scriptPubKey);
1316 }
1317 
IsMine(const CTxDestination & dest) const1318 isminetype CWallet::IsMine(const CTxDestination& dest) const
1319 {
1320     AssertLockHeld(cs_wallet);
1321     return IsMine(GetScriptForDestination(dest));
1322 }
1323 
IsMine(const CScript & script) const1324 isminetype CWallet::IsMine(const CScript& script) const
1325 {
1326     AssertLockHeld(cs_wallet);
1327     isminetype result = ISMINE_NO;
1328     for (const auto& spk_man_pair : m_spk_managers) {
1329         result = std::max(result, spk_man_pair.second->IsMine(script));
1330     }
1331     return result;
1332 }
1333 
IsMine(const CTransaction & tx) const1334 bool CWallet::IsMine(const CTransaction& tx) const
1335 {
1336     AssertLockHeld(cs_wallet);
1337     for (const CTxOut& txout : tx.vout)
1338         if (IsMine(txout))
1339             return true;
1340     return false;
1341 }
1342 
IsFromMe(const CTransaction & tx) const1343 bool CWallet::IsFromMe(const CTransaction& tx) const
1344 {
1345     return (GetDebit(tx, ISMINE_ALL) > 0);
1346 }
1347 
GetDebit(const CTransaction & tx,const isminefilter & filter) const1348 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1349 {
1350     CAmount nDebit = 0;
1351     for (const CTxIn& txin : tx.vin)
1352     {
1353         nDebit += GetDebit(txin, filter);
1354         if (!MoneyRange(nDebit))
1355             throw std::runtime_error(std::string(__func__) + ": value out of range");
1356     }
1357     return nDebit;
1358 }
1359 
IsHDEnabled() const1360 bool CWallet::IsHDEnabled() const
1361 {
1362     // All Active ScriptPubKeyMans must be HD for this to be true
1363     bool result = true;
1364     for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
1365         result &= spk_man->IsHDEnabled();
1366     }
1367     return result;
1368 }
1369 
CanGetAddresses(bool internal) const1370 bool CWallet::CanGetAddresses(bool internal) const
1371 {
1372     LOCK(cs_wallet);
1373     if (m_spk_managers.empty()) return false;
1374     for (OutputType t : OUTPUT_TYPES) {
1375         auto spk_man = GetScriptPubKeyMan(t, internal);
1376         if (spk_man && spk_man->CanGetAddresses(internal)) {
1377             return true;
1378         }
1379     }
1380     return false;
1381 }
1382 
SetWalletFlag(uint64_t flags)1383 void CWallet::SetWalletFlag(uint64_t flags)
1384 {
1385     LOCK(cs_wallet);
1386     m_wallet_flags |= flags;
1387     if (!WalletBatch(GetDatabase()).WriteWalletFlags(m_wallet_flags))
1388         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1389 }
1390 
UnsetWalletFlag(uint64_t flag)1391 void CWallet::UnsetWalletFlag(uint64_t flag)
1392 {
1393     WalletBatch batch(GetDatabase());
1394     UnsetWalletFlagWithDB(batch, flag);
1395 }
1396 
UnsetWalletFlagWithDB(WalletBatch & batch,uint64_t flag)1397 void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
1398 {
1399     LOCK(cs_wallet);
1400     m_wallet_flags &= ~flag;
1401     if (!batch.WriteWalletFlags(m_wallet_flags))
1402         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1403 }
1404 
UnsetBlankWalletFlag(WalletBatch & batch)1405 void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
1406 {
1407     UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
1408 }
1409 
IsWalletFlagSet(uint64_t flag) const1410 bool CWallet::IsWalletFlagSet(uint64_t flag) const
1411 {
1412     return (m_wallet_flags & flag);
1413 }
1414 
LoadWalletFlags(uint64_t flags)1415 bool CWallet::LoadWalletFlags(uint64_t flags)
1416 {
1417     LOCK(cs_wallet);
1418     if (((flags & KNOWN_WALLET_FLAGS) >> 32) ^ (flags >> 32)) {
1419         // contains unknown non-tolerable wallet flags
1420         return false;
1421     }
1422     m_wallet_flags = flags;
1423 
1424     return true;
1425 }
1426 
AddWalletFlags(uint64_t flags)1427 bool CWallet::AddWalletFlags(uint64_t flags)
1428 {
1429     LOCK(cs_wallet);
1430     // We should never be writing unknown non-tolerable wallet flags
1431     assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
1432     if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
1433         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1434     }
1435 
1436     return LoadWalletFlags(flags);
1437 }
1438 
1439 // Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1440 // or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
DummySignInput(CTxIn & tx_in,const CTxOut & txout,bool use_max_sig) const1441 bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
1442 {
1443     // Fill in dummy signatures for fee calculation.
1444     const CScript& scriptPubKey = txout.scriptPubKey;
1445     SignatureData sigdata;
1446 
1447     std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
1448     if (!provider) {
1449         // We don't know about this scriptpbuKey;
1450         return false;
1451     }
1452 
1453     if (!ProduceSignature(*provider, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
1454         return false;
1455     }
1456     UpdateInput(tx_in, sigdata);
1457     return true;
1458 }
1459 
1460 // Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
DummySignTx(CMutableTransaction & txNew,const std::vector<CTxOut> & txouts,bool use_max_sig) const1461 bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
1462 {
1463     // Fill in dummy signatures for fee calculation.
1464     int nIn = 0;
1465     for (const auto& txout : txouts)
1466     {
1467         if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
1468             return false;
1469         }
1470 
1471         nIn++;
1472     }
1473     return true;
1474 }
1475 
ImportScripts(const std::set<CScript> scripts,int64_t timestamp)1476 bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1477 {
1478     auto spk_man = GetLegacyScriptPubKeyMan();
1479     if (!spk_man) {
1480         return false;
1481     }
1482     LOCK(spk_man->cs_KeyStore);
1483     return spk_man->ImportScripts(scripts, timestamp);
1484 }
1485 
ImportPrivKeys(const std::map<CKeyID,CKey> & privkey_map,const int64_t timestamp)1486 bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1487 {
1488     auto spk_man = GetLegacyScriptPubKeyMan();
1489     if (!spk_man) {
1490         return false;
1491     }
1492     LOCK(spk_man->cs_KeyStore);
1493     return spk_man->ImportPrivKeys(privkey_map, timestamp);
1494 }
1495 
ImportPubKeys(const std::vector<CKeyID> & ordered_pubkeys,const std::map<CKeyID,CPubKey> & pubkey_map,const std::map<CKeyID,std::pair<CPubKey,KeyOriginInfo>> & key_origins,const bool add_keypool,const bool internal,const int64_t timestamp)1496 bool CWallet::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp)
1497 {
1498     auto spk_man = GetLegacyScriptPubKeyMan();
1499     if (!spk_man) {
1500         return false;
1501     }
1502     LOCK(spk_man->cs_KeyStore);
1503     return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, internal, timestamp);
1504 }
1505 
ImportScriptPubKeys(const std::string & label,const std::set<CScript> & script_pub_keys,const bool have_solving_data,const bool apply_label,const int64_t timestamp)1506 bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
1507 {
1508     auto spk_man = GetLegacyScriptPubKeyMan();
1509     if (!spk_man) {
1510         return false;
1511     }
1512     LOCK(spk_man->cs_KeyStore);
1513     if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1514         return false;
1515     }
1516     if (apply_label) {
1517         WalletBatch batch(GetDatabase());
1518         for (const CScript& script : script_pub_keys) {
1519             CTxDestination dest;
1520             ExtractDestination(script, dest);
1521             if (IsValidDestination(dest)) {
1522                 SetAddressBookWithDB(batch, dest, label, "receive");
1523             }
1524         }
1525     }
1526     return true;
1527 }
1528 
1529 /**
1530  * Scan active chain for relevant transactions after importing keys. This should
1531  * be called whenever new keys are added to the wallet, with the oldest key
1532  * creation time.
1533  *
1534  * @return Earliest timestamp that could be successfully scanned from. Timestamp
1535  * returned will be higher than startTime if relevant blocks could not be read.
1536  */
RescanFromTime(int64_t startTime,const WalletRescanReserver & reserver,bool update)1537 int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1538 {
1539     // Find starting block. May be null if nCreateTime is greater than the
1540     // highest blockchain timestamp, in which case there is nothing that needs
1541     // to be scanned.
1542     int start_height = 0;
1543     uint256 start_block;
1544     bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1545     WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
1546 
1547     if (start) {
1548         // TODO: this should take into account failure by ScanResult::USER_ABORT
1549         ScanResult result = ScanForWalletTransactions(start_block, start_height, {} /* max_height */, reserver, update);
1550         if (result.status == ScanResult::FAILURE) {
1551             int64_t time_max;
1552             CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
1553             return time_max + TIMESTAMP_WINDOW + 1;
1554         }
1555     }
1556     return startTime;
1557 }
1558 
1559 /**
1560  * Scan the block chain (starting in start_block) for transactions
1561  * from or to us. If fUpdate is true, found transactions that already
1562  * exist in the wallet will be updated.
1563  *
1564  * @param[in] start_block Scan starting block. If block is not on the active
1565  *                        chain, the scan will return SUCCESS immediately.
1566  * @param[in] start_height Height of start_block
1567  * @param[in] max_height  Optional max scanning height. If unset there is
1568  *                        no maximum and scanning can continue to the tip
1569  *
1570  * @return ScanResult returning scan information and indicating success or
1571  *         failure. Return status will be set to SUCCESS if scan was
1572  *         successful. FAILURE if a complete rescan was not possible (due to
1573  *         pruning or corruption). USER_ABORT if the rescan was aborted before
1574  *         it could complete.
1575  *
1576  * @pre Caller needs to make sure start_block (and the optional stop_block) are on
1577  * the main chain after to the addition of any new keys you want to detect
1578  * transactions for.
1579  */
ScanForWalletTransactions(const uint256 & start_block,int start_height,std::optional<int> max_height,const WalletRescanReserver & reserver,bool fUpdate)1580 CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
1581 {
1582     int64_t nNow = GetTime();
1583     int64_t start_time = GetTimeMillis();
1584 
1585     assert(reserver.isReserved());
1586 
1587     uint256 block_hash = start_block;
1588     ScanResult result;
1589 
1590     WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
1591 
1592     fAbortRescan = false;
1593     ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
1594     uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1595     uint256 end_hash = tip_hash;
1596     if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash));
1597     double progress_begin = chain().guessVerificationProgress(block_hash);
1598     double progress_end = chain().guessVerificationProgress(end_hash);
1599     double progress_current = progress_begin;
1600     int block_height = start_height;
1601     while (!fAbortRescan && !chain().shutdownRequested()) {
1602         if (progress_end - progress_begin > 0.0) {
1603             m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1604         } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
1605             m_scanning_progress = 0;
1606         }
1607         if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1608             ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1609         }
1610         if (GetTime() >= nNow + 60) {
1611             nNow = GetTime();
1612             WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
1613         }
1614 
1615         // Read block data
1616         CBlock block;
1617         chain().findBlock(block_hash, FoundBlock().data(block));
1618 
1619         // Find next block separately from reading data above, because reading
1620         // is slow and there might be a reorg while it is read.
1621         bool block_still_active = false;
1622         bool next_block = false;
1623         uint256 next_block_hash;
1624         chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
1625 
1626         if (!block.IsNull()) {
1627             LOCK(cs_wallet);
1628             if (!block_still_active) {
1629                 // Abort scan if current block is no longer active, to prevent
1630                 // marking transactions as coming from the wrong block.
1631                 result.last_failed_block = block_hash;
1632                 result.status = ScanResult::FAILURE;
1633                 break;
1634             }
1635             for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1636                 SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1637             }
1638             // scan succeeded, record block as most recent successfully scanned
1639             result.last_scanned_block = block_hash;
1640             result.last_scanned_height = block_height;
1641         } else {
1642             // could not scan block, keep scanning but record this block as the most recent failure
1643             result.last_failed_block = block_hash;
1644             result.status = ScanResult::FAILURE;
1645         }
1646         if (max_height && block_height >= *max_height) {
1647             break;
1648         }
1649         {
1650             if (!next_block) {
1651                 // break successfully when rescan has reached the tip, or
1652                 // previous block is no longer on the chain due to a reorg
1653                 break;
1654             }
1655 
1656             // increment block and verification progress
1657             block_hash = next_block_hash;
1658             ++block_height;
1659             progress_current = chain().guessVerificationProgress(block_hash);
1660 
1661             // handle updated tip hash
1662             const uint256 prev_tip_hash = tip_hash;
1663             tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash());
1664             if (!max_height && prev_tip_hash != tip_hash) {
1665                 // in case the tip has changed, update progress max
1666                 progress_end = chain().guessVerificationProgress(tip_hash);
1667             }
1668         }
1669     }
1670     ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 100); // hide progress dialog in GUI
1671     if (block_height && fAbortRescan) {
1672         WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
1673         result.status = ScanResult::USER_ABORT;
1674     } else if (block_height && chain().shutdownRequested()) {
1675         WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
1676         result.status = ScanResult::USER_ABORT;
1677     } else {
1678         WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
1679     }
1680     return result;
1681 }
1682 
ReacceptWalletTransactions()1683 void CWallet::ReacceptWalletTransactions()
1684 {
1685     // If transactions aren't being broadcasted, don't let them into local mempool either
1686     if (!fBroadcastTransactions)
1687         return;
1688     std::map<int64_t, CWalletTx*> mapSorted;
1689 
1690     // Sort pending wallet transactions based on their initial wallet insertion order
1691     for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1692         const uint256& wtxid = item.first;
1693         CWalletTx& wtx = item.second;
1694         assert(wtx.GetHash() == wtxid);
1695 
1696         int nDepth = wtx.GetDepthInMainChain();
1697 
1698         if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
1699             mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
1700         }
1701     }
1702 
1703     // Try to add wallet transactions to memory pool
1704     for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1705         CWalletTx& wtx = *(item.second);
1706         std::string unused_err_string;
1707         wtx.SubmitMemoryPoolAndRelay(unused_err_string, false);
1708     }
1709 }
1710 
SubmitMemoryPoolAndRelay(std::string & err_string,bool relay)1711 bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay)
1712 {
1713     // Can't relay if wallet is not broadcasting
1714     if (!pwallet->GetBroadcastTransactions()) return false;
1715     // Don't relay abandoned transactions
1716     if (isAbandoned()) return false;
1717     // Don't try to submit coinbase transactions. These would fail anyway but would
1718     // cause log spam.
1719     if (IsCoinBase()) return false;
1720     // Don't try to submit conflicted or confirmed transactions.
1721     if (GetDepthInMainChain() != 0) return false;
1722 
1723     // Submit transaction to mempool for relay
1724     pwallet->WalletLogPrintf("Submitting wtx %s to mempool for relay\n", GetHash().ToString());
1725     // We must set fInMempool here - while it will be re-set to true by the
1726     // entered-mempool callback, if we did not there would be a race where a
1727     // user could call sendmoney in a loop and hit spurious out of funds errors
1728     // because we think that this newly generated transaction's change is
1729     // unavailable as we're not yet aware that it is in the mempool.
1730     //
1731     // Irrespective of the failure reason, un-marking fInMempool
1732     // out-of-order is incorrect - it should be unmarked when
1733     // TransactionRemovedFromMempool fires.
1734     bool ret = pwallet->chain().broadcastTransaction(tx, pwallet->m_default_max_tx_fee, relay, err_string);
1735     fInMempool |= ret;
1736     return ret;
1737 }
1738 
GetConflicts() const1739 std::set<uint256> CWalletTx::GetConflicts() const
1740 {
1741     std::set<uint256> result;
1742     if (pwallet != nullptr)
1743     {
1744         uint256 myHash = GetHash();
1745         result = pwallet->GetConflicts(myHash);
1746         result.erase(myHash);
1747     }
1748     return result;
1749 }
1750 
1751 // Rebroadcast transactions from the wallet. We do this on a random timer
1752 // to slightly obfuscate which transactions come from our wallet.
1753 //
1754 // Ideally, we'd only resend transactions that we think should have been
1755 // mined in the most recent block. Any transaction that wasn't in the top
1756 // blockweight of transactions in the mempool shouldn't have been mined,
1757 // and so is probably just sitting in the mempool waiting to be confirmed.
1758 // Rebroadcasting does nothing to speed up confirmation and only damages
1759 // privacy.
ResendWalletTransactions()1760 void CWallet::ResendWalletTransactions()
1761 {
1762     // During reindex, importing and IBD, old wallet transactions become
1763     // unconfirmed. Don't resend them as that would spam other nodes.
1764     if (!chain().isReadyToBroadcast()) return;
1765 
1766     // Do this infrequently and randomly to avoid giving away
1767     // that these are our transactions.
1768     if (GetTime() < nNextResend || !fBroadcastTransactions) return;
1769     bool fFirst = (nNextResend == 0);
1770     // resend 12-36 hours from now, ~1 day on average.
1771     nNextResend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60);
1772     if (fFirst) return;
1773 
1774     int submitted_tx_count = 0;
1775 
1776     { // cs_wallet scope
1777         LOCK(cs_wallet);
1778 
1779         // Relay transactions
1780         for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1781             CWalletTx& wtx = item.second;
1782             // Attempt to rebroadcast all txes more than 5 minutes older than
1783             // the last block. SubmitMemoryPoolAndRelay() will not rebroadcast
1784             // any confirmed or conflicting txs.
1785             if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
1786             std::string unused_err_string;
1787             if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
1788         }
1789     } // cs_wallet
1790 
1791     if (submitted_tx_count > 0) {
1792         WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
1793     }
1794 }
1795 
1796 /** @} */ // end of mapWallet
1797 
MaybeResendWalletTxs()1798 void MaybeResendWalletTxs()
1799 {
1800     for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
1801         pwallet->ResendWalletTransactions();
1802     }
1803 }
1804 
1805 
1806 /** @defgroup Actions
1807  *
1808  * @{
1809  */
1810 
SignTransaction(CMutableTransaction & tx) const1811 bool CWallet::SignTransaction(CMutableTransaction& tx) const
1812 {
1813     AssertLockHeld(cs_wallet);
1814 
1815     // Build coins map
1816     std::map<COutPoint, Coin> coins;
1817     for (auto& input : tx.vin) {
1818         std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
1819         if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
1820             return false;
1821         }
1822         const CWalletTx& wtx = mi->second;
1823         coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], wtx.m_confirm.block_height, wtx.IsCoinBase());
1824     }
1825     std::map<int, std::string> input_errors;
1826     return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
1827 }
1828 
SignTransaction(CMutableTransaction & tx,const std::map<COutPoint,Coin> & coins,int sighash,std::map<int,std::string> & input_errors) const1829 bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
1830 {
1831     // Try to sign with all ScriptPubKeyMans
1832     for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
1833         // spk_man->SignTransaction will return true if the transaction is complete,
1834         // so we can exit early and return true if that happens
1835         if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
1836             return true;
1837         }
1838     }
1839 
1840     // At this point, one input was not fully signed otherwise we would have exited already
1841     return false;
1842 }
1843 
FillPSBT(PartiallySignedTransaction & psbtx,bool & complete,int sighash_type,bool sign,bool bip32derivs,size_t * n_signed) const1844 TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed) const
1845 {
1846     if (n_signed) {
1847         *n_signed = 0;
1848     }
1849     const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
1850     LOCK(cs_wallet);
1851     // Get all of the previous transactions
1852     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
1853         const CTxIn& txin = psbtx.tx->vin[i];
1854         PSBTInput& input = psbtx.inputs.at(i);
1855 
1856         if (PSBTInputSigned(input)) {
1857             continue;
1858         }
1859 
1860         // If we have no utxo, grab it from the wallet.
1861         if (!input.non_witness_utxo) {
1862             const uint256& txhash = txin.prevout.hash;
1863             const auto it = mapWallet.find(txhash);
1864             if (it != mapWallet.end()) {
1865                 const CWalletTx& wtx = it->second;
1866                 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
1867                 //   The signing code will switch to the smaller witness_utxo if this is ok.
1868                 input.non_witness_utxo = wtx.tx;
1869             }
1870         }
1871     }
1872 
1873     // Fill in information from ScriptPubKeyMans
1874     for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
1875         int n_signed_this_spkm = 0;
1876         TransactionError res = spk_man->FillPSBT(psbtx, txdata, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
1877         if (res != TransactionError::OK) {
1878             return res;
1879         }
1880 
1881         if (n_signed) {
1882             (*n_signed) += n_signed_this_spkm;
1883         }
1884     }
1885 
1886     // Complete if every input is now signed
1887     complete = true;
1888     for (const auto& input : psbtx.inputs) {
1889         complete &= PSBTInputSigned(input);
1890     }
1891 
1892     return TransactionError::OK;
1893 }
1894 
SignMessage(const std::string & message,const PKHash & pkhash,std::string & str_sig) const1895 SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
1896 {
1897     SignatureData sigdata;
1898     CScript script_pub_key = GetScriptForDestination(pkhash);
1899     for (const auto& spk_man_pair : m_spk_managers) {
1900         if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
1901             return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
1902         }
1903     }
1904     return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
1905 }
1906 
TransactionChangeType(const std::optional<OutputType> & change_type,const std::vector<CRecipient> & vecSend) const1907 OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
1908 {
1909     // If -changetype is specified, always use that change type.
1910     if (change_type) {
1911         return *change_type;
1912     }
1913 
1914     // if m_default_address_type is legacy, use legacy address as change (even
1915     // if some of the outputs are P2WPKH or P2WSH).
1916     if (m_default_address_type == OutputType::LEGACY) {
1917         return OutputType::LEGACY;
1918     }
1919 
1920     // if any destination is P2WPKH or P2WSH, use P2WPKH for the change
1921     // output.
1922     for (const auto& recipient : vecSend) {
1923         // Check if any destination contains a witness program:
1924         int witnessversion = 0;
1925         std::vector<unsigned char> witnessprogram;
1926         if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
1927             if (GetScriptPubKeyMan(OutputType::BECH32M, true)) {
1928                 return OutputType::BECH32M;
1929             } else if (GetScriptPubKeyMan(OutputType::BECH32, true)) {
1930                 return OutputType::BECH32;
1931             } else {
1932                 return m_default_address_type;
1933             }
1934         }
1935     }
1936 
1937     // else use m_default_address_type for change
1938     return m_default_address_type;
1939 }
1940 
CommitTransaction(CTransactionRef tx,mapValue_t mapValue,std::vector<std::pair<std::string,std::string>> orderForm)1941 void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
1942 {
1943     LOCK(cs_wallet);
1944     WalletLogPrintf("CommitTransaction:\n%s", tx->ToString()); /* Continued */
1945 
1946     // Add tx to wallet, because if it has change it's also ours,
1947     // otherwise just for transaction history.
1948     AddToWallet(tx, {}, [&](CWalletTx& wtx, bool new_tx) {
1949         CHECK_NONFATAL(wtx.mapValue.empty());
1950         CHECK_NONFATAL(wtx.vOrderForm.empty());
1951         wtx.mapValue = std::move(mapValue);
1952         wtx.vOrderForm = std::move(orderForm);
1953         wtx.fTimeReceivedIsTxTime = true;
1954         wtx.fFromMe = true;
1955         return true;
1956     });
1957 
1958     // Notify that old coins are spent
1959     for (const CTxIn& txin : tx->vin) {
1960         CWalletTx &coin = mapWallet.at(txin.prevout.hash);
1961         coin.MarkDirty();
1962         NotifyTransactionChanged(coin.GetHash(), CT_UPDATED);
1963     }
1964 
1965     // Get the inserted-CWalletTx from mapWallet so that the
1966     // fInMempool flag is cached properly
1967     CWalletTx& wtx = mapWallet.at(tx->GetHash());
1968 
1969     if (!fBroadcastTransactions) {
1970         // Don't submit tx to the mempool
1971         return;
1972     }
1973 
1974     std::string err_string;
1975     if (!wtx.SubmitMemoryPoolAndRelay(err_string, true)) {
1976         WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
1977         // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
1978     }
1979 }
1980 
LoadWallet()1981 DBErrors CWallet::LoadWallet()
1982 {
1983     LOCK(cs_wallet);
1984 
1985     DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
1986     if (nLoadWalletRet == DBErrors::NEED_REWRITE)
1987     {
1988         if (GetDatabase().Rewrite("\x04pool"))
1989         {
1990             for (const auto& spk_man_pair : m_spk_managers) {
1991                 spk_man_pair.second->RewriteDB();
1992             }
1993         }
1994     }
1995 
1996     if (m_spk_managers.empty()) {
1997         assert(m_external_spk_managers.empty());
1998         assert(m_internal_spk_managers.empty());
1999     }
2000 
2001     if (nLoadWalletRet != DBErrors::LOAD_OK)
2002         return nLoadWalletRet;
2003 
2004     return DBErrors::LOAD_OK;
2005 }
2006 
ZapSelectTx(std::vector<uint256> & vHashIn,std::vector<uint256> & vHashOut)2007 DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
2008 {
2009     AssertLockHeld(cs_wallet);
2010     DBErrors nZapSelectTxRet = WalletBatch(GetDatabase()).ZapSelectTx(vHashIn, vHashOut);
2011     for (const uint256& hash : vHashOut) {
2012         const auto& it = mapWallet.find(hash);
2013         wtxOrdered.erase(it->second.m_it_wtxOrdered);
2014         for (const auto& txin : it->second.tx->vin)
2015             mapTxSpends.erase(txin.prevout);
2016         mapWallet.erase(it);
2017         NotifyTransactionChanged(hash, CT_DELETED);
2018     }
2019 
2020     if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
2021     {
2022         if (GetDatabase().Rewrite("\x04pool"))
2023         {
2024             for (const auto& spk_man_pair : m_spk_managers) {
2025                 spk_man_pair.second->RewriteDB();
2026             }
2027         }
2028     }
2029 
2030     if (nZapSelectTxRet != DBErrors::LOAD_OK)
2031         return nZapSelectTxRet;
2032 
2033     MarkDirty();
2034 
2035     return DBErrors::LOAD_OK;
2036 }
2037 
SetAddressBookWithDB(WalletBatch & batch,const CTxDestination & address,const std::string & strName,const std::string & strPurpose)2038 bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
2039 {
2040     bool fUpdated = false;
2041     bool is_mine;
2042     {
2043         LOCK(cs_wallet);
2044         std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
2045         fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
2046         m_address_book[address].SetLabel(strName);
2047         if (!strPurpose.empty()) /* update purpose only if requested */
2048             m_address_book[address].purpose = strPurpose;
2049         is_mine = IsMine(address) != ISMINE_NO;
2050     }
2051     NotifyAddressBookChanged(address, strName, is_mine,
2052                              strPurpose, (fUpdated ? CT_UPDATED : CT_NEW));
2053     if (!strPurpose.empty() && !batch.WritePurpose(EncodeDestination(address), strPurpose))
2054         return false;
2055     return batch.WriteName(EncodeDestination(address), strName);
2056 }
2057 
SetAddressBook(const CTxDestination & address,const std::string & strName,const std::string & strPurpose)2058 bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
2059 {
2060     WalletBatch batch(GetDatabase());
2061     return SetAddressBookWithDB(batch, address, strName, strPurpose);
2062 }
2063 
DelAddressBook(const CTxDestination & address)2064 bool CWallet::DelAddressBook(const CTxDestination& address)
2065 {
2066     bool is_mine;
2067     WalletBatch batch(GetDatabase());
2068     {
2069         LOCK(cs_wallet);
2070         // If we want to delete receiving addresses, we need to take care that DestData "used" (and possibly newer DestData) gets preserved (and the "deleted" address transformed into a change entry instead of actually being deleted)
2071         // NOTE: This isn't a problem for sending addresses because they never have any DestData yet!
2072         // When adding new DestData, it should be considered here whether to retain or delete it (or move it?).
2073         if (IsMine(address)) {
2074             WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, PACKAGE_BUGREPORT);
2075             return false;
2076         }
2077         // Delete destdata tuples associated with address
2078         std::string strAddress = EncodeDestination(address);
2079         for (const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
2080         {
2081             batch.EraseDestData(strAddress, item.first);
2082         }
2083         m_address_book.erase(address);
2084         is_mine = IsMine(address) != ISMINE_NO;
2085     }
2086 
2087     NotifyAddressBookChanged(address, "", is_mine, "", CT_DELETED);
2088 
2089     batch.ErasePurpose(EncodeDestination(address));
2090     return batch.EraseName(EncodeDestination(address));
2091 }
2092 
KeypoolCountExternalKeys() const2093 size_t CWallet::KeypoolCountExternalKeys() const
2094 {
2095     AssertLockHeld(cs_wallet);
2096 
2097     auto legacy_spk_man = GetLegacyScriptPubKeyMan();
2098     if (legacy_spk_man) {
2099         return legacy_spk_man->KeypoolCountExternalKeys();
2100     }
2101 
2102     unsigned int count = 0;
2103     for (auto spk_man : m_external_spk_managers) {
2104         count += spk_man.second->GetKeyPoolSize();
2105     }
2106 
2107     return count;
2108 }
2109 
GetKeyPoolSize() const2110 unsigned int CWallet::GetKeyPoolSize() const
2111 {
2112     AssertLockHeld(cs_wallet);
2113 
2114     unsigned int count = 0;
2115     for (auto spk_man : GetActiveScriptPubKeyMans()) {
2116         count += spk_man->GetKeyPoolSize();
2117     }
2118     return count;
2119 }
2120 
TopUpKeyPool(unsigned int kpSize)2121 bool CWallet::TopUpKeyPool(unsigned int kpSize)
2122 {
2123     LOCK(cs_wallet);
2124     bool res = true;
2125     for (auto spk_man : GetActiveScriptPubKeyMans()) {
2126         res &= spk_man->TopUp(kpSize);
2127     }
2128     return res;
2129 }
2130 
GetNewDestination(const OutputType type,const std::string label,CTxDestination & dest,std::string & error)2131 bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error)
2132 {
2133     LOCK(cs_wallet);
2134     error.clear();
2135     bool result = false;
2136     auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
2137     if (spk_man) {
2138         spk_man->TopUp();
2139         result = spk_man->GetNewDestination(type, dest, error);
2140     } else {
2141         error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
2142     }
2143     if (result) {
2144         SetAddressBook(dest, label, "receive");
2145     }
2146 
2147     return result;
2148 }
2149 
GetNewChangeDestination(const OutputType type,CTxDestination & dest,std::string & error)2150 bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error)
2151 {
2152     LOCK(cs_wallet);
2153     error.clear();
2154 
2155     ReserveDestination reservedest(this, type);
2156     if (!reservedest.GetReservedDestination(dest, true, error)) {
2157         return false;
2158     }
2159 
2160     reservedest.KeepDestination();
2161     return true;
2162 }
2163 
GetOldestKeyPoolTime() const2164 int64_t CWallet::GetOldestKeyPoolTime() const
2165 {
2166     LOCK(cs_wallet);
2167     int64_t oldestKey = std::numeric_limits<int64_t>::max();
2168     for (const auto& spk_man_pair : m_spk_managers) {
2169         oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
2170     }
2171     return oldestKey;
2172 }
2173 
MarkDestinationsDirty(const std::set<CTxDestination> & destinations)2174 void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
2175     for (auto& entry : mapWallet) {
2176         CWalletTx& wtx = entry.second;
2177         if (wtx.m_is_cache_empty) continue;
2178         for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2179             CTxDestination dst;
2180             if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
2181                 wtx.MarkDirty();
2182                 break;
2183             }
2184         }
2185     }
2186 }
2187 
GetLabelAddresses(const std::string & label) const2188 std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
2189 {
2190     LOCK(cs_wallet);
2191     std::set<CTxDestination> result;
2192     for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
2193     {
2194         if (item.second.IsChange()) continue;
2195         const CTxDestination& address = item.first;
2196         const std::string& strName = item.second.GetLabel();
2197         if (strName == label)
2198             result.insert(address);
2199     }
2200     return result;
2201 }
2202 
GetReservedDestination(CTxDestination & dest,bool internal,std::string & error)2203 bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, std::string& error)
2204 {
2205     m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
2206     if (!m_spk_man) {
2207         error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
2208         return false;
2209     }
2210 
2211 
2212     if (nIndex == -1)
2213     {
2214         m_spk_man->TopUp();
2215 
2216         CKeyPool keypool;
2217         if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool, error)) {
2218             return false;
2219         }
2220         fInternal = keypool.fInternal;
2221     }
2222     dest = address;
2223     return true;
2224 }
2225 
KeepDestination()2226 void ReserveDestination::KeepDestination()
2227 {
2228     if (nIndex != -1) {
2229         m_spk_man->KeepDestination(nIndex, type);
2230     }
2231     nIndex = -1;
2232     address = CNoDestination();
2233 }
2234 
ReturnDestination()2235 void ReserveDestination::ReturnDestination()
2236 {
2237     if (nIndex != -1) {
2238         m_spk_man->ReturnDestination(nIndex, fInternal, address);
2239     }
2240     nIndex = -1;
2241     address = CNoDestination();
2242 }
2243 
DisplayAddress(const CTxDestination & dest)2244 bool CWallet::DisplayAddress(const CTxDestination& dest)
2245 {
2246     CScript scriptPubKey = GetScriptForDestination(dest);
2247     const auto spk_man = GetScriptPubKeyMan(scriptPubKey);
2248     if (spk_man == nullptr) {
2249         return false;
2250     }
2251     auto signer_spk_man = dynamic_cast<ExternalSignerScriptPubKeyMan*>(spk_man);
2252     if (signer_spk_man == nullptr) {
2253         return false;
2254     }
2255     ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
2256     return signer_spk_man->DisplayAddress(scriptPubKey, signer);
2257 }
2258 
LockCoin(const COutPoint & output)2259 void CWallet::LockCoin(const COutPoint& output)
2260 {
2261     AssertLockHeld(cs_wallet);
2262     setLockedCoins.insert(output);
2263 }
2264 
UnlockCoin(const COutPoint & output)2265 void CWallet::UnlockCoin(const COutPoint& output)
2266 {
2267     AssertLockHeld(cs_wallet);
2268     setLockedCoins.erase(output);
2269 }
2270 
UnlockAllCoins()2271 void CWallet::UnlockAllCoins()
2272 {
2273     AssertLockHeld(cs_wallet);
2274     setLockedCoins.clear();
2275 }
2276 
IsLockedCoin(uint256 hash,unsigned int n) const2277 bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
2278 {
2279     AssertLockHeld(cs_wallet);
2280     COutPoint outpt(hash, n);
2281 
2282     return (setLockedCoins.count(outpt) > 0);
2283 }
2284 
ListLockedCoins(std::vector<COutPoint> & vOutpts) const2285 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
2286 {
2287     AssertLockHeld(cs_wallet);
2288     for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
2289          it != setLockedCoins.end(); it++) {
2290         COutPoint outpt = (*it);
2291         vOutpts.push_back(outpt);
2292     }
2293 }
2294 
2295 /** @} */ // end of Actions
2296 
GetKeyBirthTimes(std::map<CKeyID,int64_t> & mapKeyBirth) const2297 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
2298     AssertLockHeld(cs_wallet);
2299     mapKeyBirth.clear();
2300 
2301     // map in which we'll infer heights of other keys
2302     std::map<CKeyID, const CWalletTx::Confirmation*> mapKeyFirstBlock;
2303     CWalletTx::Confirmation max_confirm;
2304     max_confirm.block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
2305     CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.block_height, FoundBlock().hash(max_confirm.hashBlock)));
2306 
2307     {
2308         LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
2309         assert(spk_man != nullptr);
2310         LOCK(spk_man->cs_KeyStore);
2311 
2312         // get birth times for keys with metadata
2313         for (const auto& entry : spk_man->mapKeyMetadata) {
2314             if (entry.second.nCreateTime) {
2315                 mapKeyBirth[entry.first] = entry.second.nCreateTime;
2316             }
2317         }
2318 
2319         // Prepare to infer birth heights for keys without metadata
2320         for (const CKeyID &keyid : spk_man->GetKeys()) {
2321             if (mapKeyBirth.count(keyid) == 0)
2322                 mapKeyFirstBlock[keyid] = &max_confirm;
2323         }
2324 
2325         // if there are no such keys, we're done
2326         if (mapKeyFirstBlock.empty())
2327             return;
2328 
2329         // find first block that affects those keys, if there are any left
2330         for (const auto& entry : mapWallet) {
2331             // iterate over all wallet transactions...
2332             const CWalletTx &wtx = entry.second;
2333             if (wtx.m_confirm.status == CWalletTx::CONFIRMED) {
2334                 // ... which are already in a block
2335                 for (const CTxOut &txout : wtx.tx->vout) {
2336                     // iterate over all their outputs
2337                     for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
2338                         // ... and all their affected keys
2339                         auto rit = mapKeyFirstBlock.find(keyid);
2340                         if (rit != mapKeyFirstBlock.end() && wtx.m_confirm.block_height < rit->second->block_height) {
2341                             rit->second = &wtx.m_confirm;
2342                         }
2343                     }
2344                 }
2345             }
2346         }
2347     }
2348 
2349     // Extract block timestamps for those keys
2350     for (const auto& entry : mapKeyFirstBlock) {
2351         int64_t block_time;
2352         CHECK_NONFATAL(chain().findBlock(entry.second->hashBlock, FoundBlock().time(block_time)));
2353         mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
2354     }
2355 }
2356 
2357 /**
2358  * Compute smart timestamp for a transaction being added to the wallet.
2359  *
2360  * Logic:
2361  * - If sending a transaction, assign its timestamp to the current time.
2362  * - If receiving a transaction outside a block, assign its timestamp to the
2363  *   current time.
2364  * - If receiving a block with a future timestamp, assign all its (not already
2365  *   known) transactions' timestamps to the current time.
2366  * - If receiving a block with a past timestamp, before the most recent known
2367  *   transaction (that we care about), assign all its (not already known)
2368  *   transactions' timestamps to the same timestamp as that most-recent-known
2369  *   transaction.
2370  * - If receiving a block with a past timestamp, but after the most recent known
2371  *   transaction, assign all its (not already known) transactions' timestamps to
2372  *   the block time.
2373  *
2374  * For more information see CWalletTx::nTimeSmart,
2375  * https://bitcointalk.org/?topic=54527, or
2376  * https://github.com/bitcoin/bitcoin/pull/1393.
2377  */
ComputeTimeSmart(const CWalletTx & wtx) const2378 unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
2379 {
2380     unsigned int nTimeSmart = wtx.nTimeReceived;
2381     if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
2382         int64_t blocktime;
2383         if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
2384             int64_t latestNow = wtx.nTimeReceived;
2385             int64_t latestEntry = 0;
2386 
2387             // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2388             int64_t latestTolerated = latestNow + 300;
2389             const TxItems& txOrdered = wtxOrdered;
2390             for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2391                 CWalletTx* const pwtx = it->second;
2392                 if (pwtx == &wtx) {
2393                     continue;
2394                 }
2395                 int64_t nSmartTime;
2396                 nSmartTime = pwtx->nTimeSmart;
2397                 if (!nSmartTime) {
2398                     nSmartTime = pwtx->nTimeReceived;
2399                 }
2400                 if (nSmartTime <= latestTolerated) {
2401                     latestEntry = nSmartTime;
2402                     if (nSmartTime > latestNow) {
2403                         latestNow = nSmartTime;
2404                     }
2405                     break;
2406                 }
2407             }
2408 
2409             nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2410         } else {
2411             WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
2412         }
2413     }
2414     return nTimeSmart;
2415 }
2416 
SetAddressUsed(WalletBatch & batch,const CTxDestination & dest,bool used)2417 bool CWallet::SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used)
2418 {
2419     const std::string key{"used"};
2420     if (std::get_if<CNoDestination>(&dest))
2421         return false;
2422 
2423     if (!used) {
2424         if (auto* data = util::FindKey(m_address_book, dest)) data->destdata.erase(key);
2425         return batch.EraseDestData(EncodeDestination(dest), key);
2426     }
2427 
2428     const std::string value{"1"};
2429     m_address_book[dest].destdata.insert(std::make_pair(key, value));
2430     return batch.WriteDestData(EncodeDestination(dest), key, value);
2431 }
2432 
LoadDestData(const CTxDestination & dest,const std::string & key,const std::string & value)2433 void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
2434 {
2435     m_address_book[dest].destdata.insert(std::make_pair(key, value));
2436 }
2437 
IsAddressUsed(const CTxDestination & dest) const2438 bool CWallet::IsAddressUsed(const CTxDestination& dest) const
2439 {
2440     const std::string key{"used"};
2441     std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
2442     if(i != m_address_book.end())
2443     {
2444         CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2445         if(j != i->second.destdata.end())
2446         {
2447             return true;
2448         }
2449     }
2450     return false;
2451 }
2452 
GetAddressReceiveRequests() const2453 std::vector<std::string> CWallet::GetAddressReceiveRequests() const
2454 {
2455     const std::string prefix{"rr"};
2456     std::vector<std::string> values;
2457     for (const auto& address : m_address_book) {
2458         for (const auto& data : address.second.destdata) {
2459             if (!data.first.compare(0, prefix.size(), prefix)) {
2460                 values.emplace_back(data.second);
2461             }
2462         }
2463     }
2464     return values;
2465 }
2466 
SetAddressReceiveRequest(WalletBatch & batch,const CTxDestination & dest,const std::string & id,const std::string & value)2467 bool CWallet::SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value)
2468 {
2469     const std::string key{"rr" + id}; // "rr" prefix = "receive request" in destdata
2470     CAddressBookData& data = m_address_book.at(dest);
2471     if (value.empty()) {
2472         if (!batch.EraseDestData(EncodeDestination(dest), key)) return false;
2473         data.destdata.erase(key);
2474     } else {
2475         if (!batch.WriteDestData(EncodeDestination(dest), key, value)) return false;
2476         data.destdata[key] = value;
2477     }
2478     return true;
2479 }
2480 
MakeWalletDatabase(const std::string & name,const DatabaseOptions & options,DatabaseStatus & status,bilingual_str & error_string)2481 std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error_string)
2482 {
2483     // Do some checking on wallet path. It should be either a:
2484     //
2485     // 1. Path where a directory can be created.
2486     // 2. Path to an existing directory.
2487     // 3. Path to a symlink to a directory.
2488     // 4. For backwards compatibility, the name of a data file in -walletdir.
2489     const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), name);
2490     fs::file_type path_type = fs::symlink_status(wallet_path).type();
2491     if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
2492           (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
2493           (path_type == fs::regular_file && fs::path(name).filename() == name))) {
2494         error_string = Untranslated(strprintf(
2495               "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
2496               "database/log.?????????? files can be stored, a location where such a directory could be created, "
2497               "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
2498               name, GetWalletDir()));
2499         status = DatabaseStatus::FAILED_BAD_PATH;
2500         return nullptr;
2501     }
2502     return MakeDatabase(wallet_path, options, status, error_string);
2503 }
2504 
Create(interfaces::Chain * chain,const std::string & name,std::unique_ptr<WalletDatabase> database,uint64_t wallet_creation_flags,bilingual_str & error,std::vector<bilingual_str> & warnings)2505 std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
2506 {
2507     const std::string& walletFile = database->Filename();
2508 
2509     int64_t nStart = GetTimeMillis();
2510     // TODO: Can't use std::make_shared because we need a custom deleter but
2511     // should be possible to use std::allocate_shared.
2512     std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), ReleaseWallet);
2513     DBErrors nLoadWalletRet = walletInstance->LoadWallet();
2514     if (nLoadWalletRet != DBErrors::LOAD_OK) {
2515         if (nLoadWalletRet == DBErrors::CORRUPT) {
2516             error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
2517             return nullptr;
2518         }
2519         else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
2520         {
2521             warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
2522                                            " or address book entries might be missing or incorrect."),
2523                 walletFile));
2524         }
2525         else if (nLoadWalletRet == DBErrors::TOO_NEW) {
2526             error = strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME);
2527             return nullptr;
2528         }
2529         else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
2530         {
2531             error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME);
2532             return nullptr;
2533         }
2534         else {
2535             error = strprintf(_("Error loading %s"), walletFile);
2536             return nullptr;
2537         }
2538     }
2539 
2540     // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
2541     const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
2542                      !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
2543                      !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
2544     if (fFirstRun)
2545     {
2546         // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
2547         walletInstance->SetMinVersion(FEATURE_LATEST);
2548 
2549         walletInstance->AddWalletFlags(wallet_creation_flags);
2550 
2551         // Only create LegacyScriptPubKeyMan when not descriptor wallet
2552         if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2553             walletInstance->SetupLegacyScriptPubKeyMan();
2554         }
2555 
2556         if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) || !(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
2557             LOCK(walletInstance->cs_wallet);
2558             if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
2559                 walletInstance->SetupDescriptorScriptPubKeyMans();
2560                 // SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
2561             } else {
2562                 // Legacy wallets need SetupGeneration here.
2563                 for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2564                     if (!spk_man->SetupGeneration()) {
2565                         error = _("Unable to generate initial keys");
2566                         return nullptr;
2567                     }
2568                 }
2569             }
2570         }
2571 
2572         if (chain) {
2573             walletInstance->chainStateFlushed(chain->getTipLocator());
2574         }
2575     } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
2576         // Make it impossible to disable private keys after creation
2577         error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
2578         return NULL;
2579     } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
2580         for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
2581             if (spk_man->HavePrivateKeys()) {
2582                 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
2583                 break;
2584             }
2585         }
2586     }
2587 
2588     if (!gArgs.GetArg("-addresstype", "").empty()) {
2589         if (!ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
2590             error = strprintf(_("Unknown address type '%s'"), gArgs.GetArg("-addresstype", ""));
2591             return nullptr;
2592         }
2593     }
2594 
2595     if (!gArgs.GetArg("-changetype", "").empty()) {
2596         OutputType out_type;
2597         if (!ParseOutputType(gArgs.GetArg("-changetype", ""), out_type)) {
2598             error = strprintf(_("Unknown change type '%s'"), gArgs.GetArg("-changetype", ""));
2599             return nullptr;
2600         }
2601         walletInstance->m_default_change_type = out_type;
2602     }
2603 
2604     if (gArgs.IsArgSet("-mintxfee")) {
2605         CAmount n = 0;
2606         if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
2607             error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""));
2608             return nullptr;
2609         }
2610         if (n > HIGH_TX_FEE_PER_KB) {
2611             warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") +
2612                                _("This is the minimum transaction fee you pay on every transaction."));
2613         }
2614         walletInstance->m_min_fee = CFeeRate(n);
2615     }
2616 
2617     if (gArgs.IsArgSet("-maxapsfee")) {
2618         const std::string max_aps_fee{gArgs.GetArg("-maxapsfee", "")};
2619         CAmount n = 0;
2620         if (max_aps_fee == "-1") {
2621             n = -1;
2622         } else if (!ParseMoney(max_aps_fee, n)) {
2623             error = AmountErrMsg("maxapsfee", max_aps_fee);
2624             return nullptr;
2625         }
2626         if (n > HIGH_APS_FEE) {
2627             warnings.push_back(AmountHighWarn("-maxapsfee") + Untranslated(" ") +
2628                               _("This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection."));
2629         }
2630         walletInstance->m_max_aps_fee = n;
2631     }
2632 
2633     if (gArgs.IsArgSet("-fallbackfee")) {
2634         CAmount nFeePerK = 0;
2635         if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
2636             error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", ""));
2637             return nullptr;
2638         }
2639         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2640             warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") +
2641                                _("This is the transaction fee you may pay when fee estimates are not available."));
2642         }
2643         walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
2644     }
2645     // Disable fallback fee in case value was set to 0, enable if non-null value
2646     walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
2647 
2648     if (gArgs.IsArgSet("-discardfee")) {
2649         CAmount nFeePerK = 0;
2650         if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
2651             error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", ""));
2652             return nullptr;
2653         }
2654         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2655             warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") +
2656                                _("This is the transaction fee you may discard if change is smaller than dust at this level"));
2657         }
2658         walletInstance->m_discard_rate = CFeeRate(nFeePerK);
2659     }
2660     if (gArgs.IsArgSet("-paytxfee")) {
2661         CAmount nFeePerK = 0;
2662         if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
2663             error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""));
2664             return nullptr;
2665         }
2666         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
2667             warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") +
2668                                _("This is the transaction fee you will pay if you send a transaction."));
2669         }
2670         walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
2671         if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
2672             error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
2673                 gArgs.GetArg("-paytxfee", ""), chain->relayMinFee().ToString());
2674             return nullptr;
2675         }
2676     }
2677 
2678     if (gArgs.IsArgSet("-maxtxfee")) {
2679         CAmount nMaxFee = 0;
2680         if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
2681             error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", ""));
2682             return nullptr;
2683         }
2684         if (nMaxFee > HIGH_MAX_TX_FEE) {
2685             warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
2686         }
2687         if (chain && CFeeRate(nMaxFee, 1000) < chain->relayMinFee()) {
2688             error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
2689                 gArgs.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
2690             return nullptr;
2691         }
2692         walletInstance->m_default_max_tx_fee = nMaxFee;
2693     }
2694 
2695     if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
2696         warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
2697                            _("The wallet will avoid paying less than the minimum relay fee."));
2698     }
2699 
2700     walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
2701     walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
2702     walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
2703 
2704     walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
2705 
2706     // Try to top up keypool. No-op if the wallet is locked.
2707     walletInstance->TopUpKeyPool();
2708 
2709     LOCK(walletInstance->cs_wallet);
2710 
2711     if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
2712         return nullptr;
2713     }
2714 
2715     {
2716         LOCK(cs_wallets);
2717         for (auto& load_wallet : g_load_wallet_fns) {
2718             load_wallet(interfaces::MakeWallet(walletInstance));
2719         }
2720     }
2721 
2722     walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
2723 
2724     {
2725         walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n",      walletInstance->GetKeyPoolSize());
2726         walletInstance->WalletLogPrintf("mapWallet.size() = %u\n",       walletInstance->mapWallet.size());
2727         walletInstance->WalletLogPrintf("m_address_book.size() = %u\n",  walletInstance->m_address_book.size());
2728     }
2729 
2730     return walletInstance;
2731 }
2732 
AttachChain(const std::shared_ptr<CWallet> & walletInstance,interfaces::Chain & chain,bilingual_str & error,std::vector<bilingual_str> & warnings)2733 bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
2734 {
2735     LOCK(walletInstance->cs_wallet);
2736     // allow setting the chain if it hasn't been set already but prevent changing it
2737     assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
2738     walletInstance->m_chain = &chain;
2739 
2740     // Register wallet with validationinterface. It's done before rescan to avoid
2741     // missing block connections between end of rescan and validation subscribing.
2742     // Because of wallet lock being hold, block connection notifications are going to
2743     // be pending on the validation-side until lock release. It's likely to have
2744     // block processing duplicata (if rescan block range overlaps with notification one)
2745     // but we guarantee at least than wallet state is correct after notifications delivery.
2746     // This is temporary until rescan and notifications delivery are unified under same
2747     // interface.
2748     walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
2749 
2750     int rescan_height = 0;
2751     if (!gArgs.GetBoolArg("-rescan", false))
2752     {
2753         WalletBatch batch(walletInstance->GetDatabase());
2754         CBlockLocator locator;
2755         if (batch.ReadBestBlock(locator)) {
2756             if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) {
2757                 rescan_height = *fork_height;
2758             }
2759         }
2760     }
2761 
2762     const std::optional<int> tip_height = chain.getHeight();
2763     if (tip_height) {
2764         walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height);
2765         walletInstance->m_last_block_processed_height = *tip_height;
2766     } else {
2767         walletInstance->m_last_block_processed.SetNull();
2768         walletInstance->m_last_block_processed_height = -1;
2769     }
2770 
2771     if (tip_height && *tip_height != rescan_height)
2772     {
2773         if (chain.havePruned()) {
2774             int block_height = *tip_height;
2775             while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
2776                 --block_height;
2777             }
2778 
2779             if (rescan_height != block_height) {
2780                 // We can't rescan beyond non-pruned blocks, stop and throw an error.
2781                 // This might happen if a user uses an old wallet within a pruned node
2782                 // or if they ran -disablewallet for a longer time, then decided to re-enable
2783                 // Exit early and print an error.
2784                 // If a block is pruned after this check, we will load the wallet,
2785                 // but fail the rescan with a generic error.
2786                 error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
2787                 return false;
2788             }
2789         }
2790 
2791         chain.initMessage(_("Rescanning…").translated);
2792         walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
2793 
2794         // No need to read and scan block if block was created before
2795         // our wallet birthday (as adjusted for block time variability)
2796         std::optional<int64_t> time_first_key;
2797         for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
2798             int64_t time = spk_man->GetTimeFirstKey();
2799             if (!time_first_key || time < *time_first_key) time_first_key = time;
2800         }
2801         if (time_first_key) {
2802             chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
2803         }
2804 
2805         {
2806             WalletRescanReserver reserver(*walletInstance);
2807             if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
2808                 error = _("Failed to rescan the wallet during initialization");
2809                 return false;
2810             }
2811         }
2812         walletInstance->chainStateFlushed(chain.getTipLocator());
2813         walletInstance->GetDatabase().IncrementUpdateCounter();
2814     }
2815 
2816     return true;
2817 }
2818 
FindAddressBookEntry(const CTxDestination & dest,bool allow_change) const2819 const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
2820 {
2821     const auto& address_book_it = m_address_book.find(dest);
2822     if (address_book_it == m_address_book.end()) return nullptr;
2823     if ((!allow_change) && address_book_it->second.IsChange()) {
2824         return nullptr;
2825     }
2826     return &address_book_it->second;
2827 }
2828 
UpgradeWallet(int version,bilingual_str & error)2829 bool CWallet::UpgradeWallet(int version, bilingual_str& error)
2830 {
2831     int prev_version = GetVersion();
2832     if (version == 0) {
2833         WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
2834         version = FEATURE_LATEST;
2835     } else {
2836         WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
2837     }
2838     if (version < prev_version) {
2839         error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
2840         return false;
2841     }
2842 
2843     LOCK(cs_wallet);
2844 
2845     // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
2846     if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && version < FEATURE_PRE_SPLIT_KEYPOOL) {
2847         error = strprintf(_("Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified."), prev_version, version, FEATURE_PRE_SPLIT_KEYPOOL);
2848         return false;
2849     }
2850 
2851     // Permanently upgrade to the version
2852     SetMinVersion(GetClosestWalletFeature(version));
2853 
2854     for (auto spk_man : GetActiveScriptPubKeyMans()) {
2855         if (!spk_man->Upgrade(prev_version, version, error)) {
2856             return false;
2857         }
2858     }
2859     return true;
2860 }
2861 
postInitProcess()2862 void CWallet::postInitProcess()
2863 {
2864     LOCK(cs_wallet);
2865 
2866     // Add wallet transactions that aren't already in a block to mempool
2867     // Do this here as mempool requires genesis block to be loaded
2868     ReacceptWalletTransactions();
2869 
2870     // Update wallet transactions with current mempool transactions.
2871     chain().requestMempoolTransactions(*this);
2872 }
2873 
BackupWallet(const std::string & strDest) const2874 bool CWallet::BackupWallet(const std::string& strDest) const
2875 {
2876     return GetDatabase().Backup(strDest);
2877 }
2878 
CKeyPool()2879 CKeyPool::CKeyPool()
2880 {
2881     nTime = GetTime();
2882     fInternal = false;
2883     m_pre_split = false;
2884 }
2885 
CKeyPool(const CPubKey & vchPubKeyIn,bool internalIn)2886 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
2887 {
2888     nTime = GetTime();
2889     vchPubKey = vchPubKeyIn;
2890     fInternal = internalIn;
2891     m_pre_split = false;
2892 }
2893 
GetDepthInMainChain() const2894 int CWalletTx::GetDepthInMainChain() const
2895 {
2896     assert(pwallet != nullptr);
2897     AssertLockHeld(pwallet->cs_wallet);
2898     if (isUnconfirmed() || isAbandoned()) return 0;
2899 
2900     return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
2901 }
2902 
GetBlocksToMaturity() const2903 int CWalletTx::GetBlocksToMaturity() const
2904 {
2905     if (!IsCoinBase())
2906         return 0;
2907     int chain_depth = GetDepthInMainChain();
2908     assert(chain_depth >= 0); // coinbase tx should not be conflicted
2909     return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
2910 }
2911 
IsImmatureCoinBase() const2912 bool CWalletTx::IsImmatureCoinBase() const
2913 {
2914     // note GetBlocksToMaturity is 0 for non-coinbase tx
2915     return GetBlocksToMaturity() > 0;
2916 }
2917 
IsCrypted() const2918 bool CWallet::IsCrypted() const
2919 {
2920     return HasEncryptionKeys();
2921 }
2922 
IsLocked() const2923 bool CWallet::IsLocked() const
2924 {
2925     if (!IsCrypted()) {
2926         return false;
2927     }
2928     LOCK(cs_wallet);
2929     return vMasterKey.empty();
2930 }
2931 
Lock()2932 bool CWallet::Lock()
2933 {
2934     if (!IsCrypted())
2935         return false;
2936 
2937     {
2938         LOCK(cs_wallet);
2939         vMasterKey.clear();
2940     }
2941 
2942     NotifyStatusChanged(this);
2943     return true;
2944 }
2945 
Unlock(const CKeyingMaterial & vMasterKeyIn,bool accept_no_keys)2946 bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
2947 {
2948     {
2949         LOCK(cs_wallet);
2950         for (const auto& spk_man_pair : m_spk_managers) {
2951             if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
2952                 return false;
2953             }
2954         }
2955         vMasterKey = vMasterKeyIn;
2956     }
2957     NotifyStatusChanged(this);
2958     return true;
2959 }
2960 
GetActiveScriptPubKeyMans() const2961 std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
2962 {
2963     std::set<ScriptPubKeyMan*> spk_mans;
2964     for (bool internal : {false, true}) {
2965         for (OutputType t : OUTPUT_TYPES) {
2966             auto spk_man = GetScriptPubKeyMan(t, internal);
2967             if (spk_man) {
2968                 spk_mans.insert(spk_man);
2969             }
2970         }
2971     }
2972     return spk_mans;
2973 }
2974 
GetAllScriptPubKeyMans() const2975 std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
2976 {
2977     std::set<ScriptPubKeyMan*> spk_mans;
2978     for (const auto& spk_man_pair : m_spk_managers) {
2979         spk_mans.insert(spk_man_pair.second.get());
2980     }
2981     return spk_mans;
2982 }
2983 
GetScriptPubKeyMan(const OutputType & type,bool internal) const2984 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
2985 {
2986     const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
2987     std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
2988     if (it == spk_managers.end()) {
2989         return nullptr;
2990     }
2991     return it->second;
2992 }
2993 
GetScriptPubKeyMans(const CScript & script,SignatureData & sigdata) const2994 std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const
2995 {
2996     std::set<ScriptPubKeyMan*> spk_mans;
2997     for (const auto& spk_man_pair : m_spk_managers) {
2998         if (spk_man_pair.second->CanProvide(script, sigdata)) {
2999             spk_mans.insert(spk_man_pair.second.get());
3000         }
3001     }
3002     return spk_mans;
3003 }
3004 
GetScriptPubKeyMan(const CScript & script) const3005 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
3006 {
3007     SignatureData sigdata;
3008     for (const auto& spk_man_pair : m_spk_managers) {
3009         if (spk_man_pair.second->CanProvide(script, sigdata)) {
3010             return spk_man_pair.second.get();
3011         }
3012     }
3013     return nullptr;
3014 }
3015 
GetScriptPubKeyMan(const uint256 & id) const3016 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
3017 {
3018     if (m_spk_managers.count(id) > 0) {
3019         return m_spk_managers.at(id).get();
3020     }
3021     return nullptr;
3022 }
3023 
GetSolvingProvider(const CScript & script) const3024 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
3025 {
3026     SignatureData sigdata;
3027     return GetSolvingProvider(script, sigdata);
3028 }
3029 
GetSolvingProvider(const CScript & script,SignatureData & sigdata) const3030 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
3031 {
3032     for (const auto& spk_man_pair : m_spk_managers) {
3033         if (spk_man_pair.second->CanProvide(script, sigdata)) {
3034             return spk_man_pair.second->GetSolvingProvider(script);
3035         }
3036     }
3037     return nullptr;
3038 }
3039 
GetLegacyScriptPubKeyMan() const3040 LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
3041 {
3042     if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3043         return nullptr;
3044     }
3045     // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
3046     // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
3047     auto it = m_internal_spk_managers.find(OutputType::LEGACY);
3048     if (it == m_internal_spk_managers.end()) return nullptr;
3049     return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
3050 }
3051 
GetOrCreateLegacyScriptPubKeyMan()3052 LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
3053 {
3054     SetupLegacyScriptPubKeyMan();
3055     return GetLegacyScriptPubKeyMan();
3056 }
3057 
SetupLegacyScriptPubKeyMan()3058 void CWallet::SetupLegacyScriptPubKeyMan()
3059 {
3060     if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3061         return;
3062     }
3063 
3064     auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this));
3065     for (const auto& type : LEGACY_OUTPUT_TYPES) {
3066         m_internal_spk_managers[type] = spk_manager.get();
3067         m_external_spk_managers[type] = spk_manager.get();
3068     }
3069     m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
3070 }
3071 
GetEncryptionKey() const3072 const CKeyingMaterial& CWallet::GetEncryptionKey() const
3073 {
3074     return vMasterKey;
3075 }
3076 
HasEncryptionKeys() const3077 bool CWallet::HasEncryptionKeys() const
3078 {
3079     return !mapMasterKeys.empty();
3080 }
3081 
ConnectScriptPubKeyManNotifiers()3082 void CWallet::ConnectScriptPubKeyManNotifiers()
3083 {
3084     for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
3085         spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
3086         spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
3087     }
3088 }
3089 
LoadDescriptorScriptPubKeyMan(uint256 id,WalletDescriptor & desc)3090 void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
3091 {
3092     if (IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
3093         auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this, desc));
3094         m_spk_managers[id] = std::move(spk_manager);
3095     } else {
3096         auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
3097         m_spk_managers[id] = std::move(spk_manager);
3098     }
3099 }
3100 
SetupDescriptorScriptPubKeyMans()3101 void CWallet::SetupDescriptorScriptPubKeyMans()
3102 {
3103     AssertLockHeld(cs_wallet);
3104 
3105     if (!IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
3106         // Make a seed
3107         CKey seed_key;
3108         seed_key.MakeNewKey(true);
3109         CPubKey seed = seed_key.GetPubKey();
3110         assert(seed_key.VerifyPubKey(seed));
3111 
3112         // Get the extended key
3113         CExtKey master_key;
3114         master_key.SetSeed(seed_key.begin(), seed_key.size());
3115 
3116         for (bool internal : {false, true}) {
3117             for (OutputType t : OUTPUT_TYPES) {
3118                 if (t == OutputType::BECH32M) {
3119                     // Skip taproot (bech32m) for now
3120                     // TODO: Setup taproot (bech32m) descriptors by default
3121                     continue;
3122                 }
3123                 auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this));
3124                 if (IsCrypted()) {
3125                     if (IsLocked()) {
3126                         throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
3127                     }
3128                     if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
3129                         throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
3130                     }
3131                 }
3132                 spk_manager->SetupDescriptorGeneration(master_key, t, internal);
3133                 uint256 id = spk_manager->GetID();
3134                 m_spk_managers[id] = std::move(spk_manager);
3135                 AddActiveScriptPubKeyMan(id, t, internal);
3136             }
3137         }
3138     } else {
3139         ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
3140 
3141         // TODO: add account parameter
3142         int account = 0;
3143         UniValue signer_res = signer.GetDescriptors(account);
3144 
3145         if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3146         for (bool internal : {false, true}) {
3147             const UniValue& descriptor_vals = find_value(signer_res, internal ? "internal" : "receive");
3148             if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
3149             for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
3150                 std::string desc_str = desc_val.getValStr();
3151                 FlatSigningProvider keys;
3152                 std::string dummy_error;
3153                 std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, dummy_error, false);
3154                 if (!desc->GetOutputType()) {
3155                     continue;
3156                 }
3157                 OutputType t =  *desc->GetOutputType();
3158                 auto spk_manager = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(*this));
3159                 spk_manager->SetupDescriptor(std::move(desc));
3160                 uint256 id = spk_manager->GetID();
3161                 m_spk_managers[id] = std::move(spk_manager);
3162                 AddActiveScriptPubKeyMan(id, t, internal);
3163             }
3164         }
3165     }
3166 }
3167 
AddActiveScriptPubKeyMan(uint256 id,OutputType type,bool internal)3168 void CWallet::AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3169 {
3170     WalletBatch batch(GetDatabase());
3171     if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
3172         throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
3173     }
3174     LoadActiveScriptPubKeyMan(id, type, internal);
3175 }
3176 
LoadActiveScriptPubKeyMan(uint256 id,OutputType type,bool internal)3177 void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3178 {
3179     // Activating ScriptPubKeyManager for a given output and change type is incompatible with legacy wallets.
3180     // Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
3181     Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
3182 
3183     WalletLogPrintf("Setting spkMan to active: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3184     auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3185     auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
3186     auto spk_man = m_spk_managers.at(id).get();
3187     spk_mans[type] = spk_man;
3188 
3189     if (spk_mans_other[type] == spk_man) {
3190         spk_mans_other.erase(type);
3191     }
3192 
3193     NotifyCanGetAddressesChanged();
3194 }
3195 
DeactivateScriptPubKeyMan(uint256 id,OutputType type,bool internal)3196 void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal)
3197 {
3198     auto spk_man = GetScriptPubKeyMan(type, internal);
3199     if (spk_man != nullptr && spk_man->GetID() == id) {
3200         WalletLogPrintf("Deactivate spkMan: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
3201         WalletBatch batch(GetDatabase());
3202         if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
3203             throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
3204         }
3205 
3206         auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
3207         spk_mans.erase(type);
3208     }
3209 
3210     NotifyCanGetAddressesChanged();
3211 }
3212 
IsLegacy() const3213 bool CWallet::IsLegacy() const
3214 {
3215     if (m_internal_spk_managers.count(OutputType::LEGACY) == 0) {
3216         return false;
3217     }
3218     auto spk_man = dynamic_cast<LegacyScriptPubKeyMan*>(m_internal_spk_managers.at(OutputType::LEGACY));
3219     return spk_man != nullptr;
3220 }
3221 
GetDescriptorScriptPubKeyMan(const WalletDescriptor & desc) const3222 DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const
3223 {
3224     for (auto& spk_man_pair : m_spk_managers) {
3225         // Try to downcast to DescriptorScriptPubKeyMan then check if the descriptors match
3226         DescriptorScriptPubKeyMan* spk_manager = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man_pair.second.get());
3227         if (spk_manager != nullptr && spk_manager->HasWalletDescriptor(desc)) {
3228             return spk_manager;
3229         }
3230     }
3231 
3232     return nullptr;
3233 }
3234 
AddWalletDescriptor(WalletDescriptor & desc,const FlatSigningProvider & signing_provider,const std::string & label,bool internal)3235 ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
3236 {
3237     if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3238         WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
3239         return nullptr;
3240     }
3241 
3242     LOCK(cs_wallet);
3243     auto spk_man = GetDescriptorScriptPubKeyMan(desc);
3244     if (spk_man) {
3245         WalletLogPrintf("Update existing descriptor: %s\n", desc.descriptor->ToString());
3246         spk_man->UpdateWalletDescriptor(desc);
3247     } else {
3248         auto new_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, desc));
3249         spk_man = new_spk_man.get();
3250 
3251         // Save the descriptor to memory
3252         m_spk_managers[new_spk_man->GetID()] = std::move(new_spk_man);
3253     }
3254 
3255     // Add the private keys to the descriptor
3256     for (const auto& entry : signing_provider.keys) {
3257         const CKey& key = entry.second;
3258         spk_man->AddDescriptorKey(key, key.GetPubKey());
3259     }
3260 
3261     // Top up key pool, the manager will generate new scriptPubKeys internally
3262     if (!spk_man->TopUp()) {
3263         WalletLogPrintf("Could not top up scriptPubKeys\n");
3264         return nullptr;
3265     }
3266 
3267     // Apply the label if necessary
3268     // Note: we disable labels for ranged descriptors
3269     if (!desc.descriptor->IsRange()) {
3270         auto script_pub_keys = spk_man->GetScriptPubKeys();
3271         if (script_pub_keys.empty()) {
3272             WalletLogPrintf("Could not generate scriptPubKeys (cache is empty)\n");
3273             return nullptr;
3274         }
3275 
3276         CTxDestination dest;
3277         if (!internal && ExtractDestination(script_pub_keys.at(0), dest)) {
3278             SetAddressBook(dest, label, "receive");
3279         }
3280     }
3281 
3282     // Save the descriptor to DB
3283     spk_man->WriteDescriptor();
3284 
3285     return spk_man;
3286 }
3287