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 <fs.h>
12 #include <interfaces/chain.h>
13 #include <interfaces/wallet.h>
14 #include <key.h>
15 #include <key_io.h>
16 #include <optional.h>
17 #include <policy/fees.h>
18 #include <policy/policy.h>
19 #include <primitives/block.h>
20 #include <primitives/transaction.h>
21 #include <script/descriptor.h>
22 #include <script/script.h>
23 #include <script/signingprovider.h>
24 #include <txmempool.h>
25 #include <util/bip32.h>
26 #include <util/error.h>
27 #include <util/fees.h>
28 #include <util/moneystr.h>
29 #include <util/rbf.h>
30 #include <util/translation.h>
31 #include <wallet/coincontrol.h>
32 #include <wallet/fees.h>
33 #include <miner.h>
34 
35 #include <algorithm>
36 #include <assert.h>
37 
38 #include <boost/algorithm/string/replace.hpp>
39 
40 const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
41     {WALLET_FLAG_AVOID_REUSE,
42         "You need to rescan the blockchain in order to correctly mark used "
43         "destinations in the past. Until this is done, some destinations may "
44         "be considered unused, even if the opposite is the case."
45     },
46 };
47 
48 static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;
49 
50 static RecursiveMutex cs_wallets;
51 static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
52 static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
53 CConnman* CWallet::defaultConnman = 0;
54 
AddWallet(const std::shared_ptr<CWallet> & wallet)55 bool AddWallet(const std::shared_ptr<CWallet>& wallet)
56 {
57     LOCK(cs_wallets);
58     assert(wallet);
59     std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
60     if (i != vpwallets.end()) return false;
61     vpwallets.push_back(wallet);
62     wallet->ConnectScriptPubKeyManNotifiers();
63     return true;
64 }
65 
RemoveWallet(const std::shared_ptr<CWallet> & wallet)66 bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
67 {
68     assert(wallet);
69     // Unregister with the validation interface which also drops shared ponters.
70     wallet->m_chain_notifications_handler.reset();
71     LOCK(cs_wallets);
72     std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
73     if (i == vpwallets.end()) return false;
74     vpwallets.erase(i);
75     return true;
76 }
77 
HasWallets()78 bool HasWallets()
79 {
80     LOCK(cs_wallets);
81     return !vpwallets.empty();
82 }
83 
GetWallets()84 std::vector<std::shared_ptr<CWallet>> GetWallets()
85 {
86     LOCK(cs_wallets);
87     return vpwallets;
88 }
89 
GetWallet(const std::string & name)90 std::shared_ptr<CWallet> GetWallet(const std::string& name)
91 {
92     LOCK(cs_wallets);
93     for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
94         if (wallet->GetName() == name) return wallet;
95     }
96     return nullptr;
97 }
98 
HandleLoadWallet(LoadWalletFn load_wallet)99 std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet)
100 {
101     LOCK(cs_wallets);
102     auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet));
103     return interfaces::MakeHandler([it] { LOCK(cs_wallets); g_load_wallet_fns.erase(it); });
104 }
105 
106 static Mutex g_loading_wallet_mutex;
107 static Mutex g_wallet_release_mutex;
108 static std::condition_variable g_wallet_release_cv;
109 static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
110 static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
111 
112 // Custom deleter for shared_ptr<CWallet>.
ReleaseWallet(CWallet * wallet)113 static void ReleaseWallet(CWallet* wallet)
114 {
115     const std::string name = wallet->GetName();
116     wallet->WalletLogPrintf("Releasing wallet\n");
117     wallet->StopStake();
118     wallet->Flush();
119     delete wallet;
120     // Wallet is now released, notify UnloadWallet, if any.
121     {
122         LOCK(g_wallet_release_mutex);
123         if (g_unloading_wallet_set.erase(name) == 0) {
124             // UnloadWallet was not called for this wallet, all done.
125             return;
126         }
127     }
128     g_wallet_release_cv.notify_all();
129 }
130 
UnloadWallet(std::shared_ptr<CWallet> && wallet)131 void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
132 {
133     // Mark wallet for unloading.
134     const std::string name = wallet->GetName();
135     {
136         LOCK(g_wallet_release_mutex);
137         auto it = g_unloading_wallet_set.insert(name);
138         assert(it.second);
139     }
140     // The wallet can be in use so it's not possible to explicitly unload here.
141     // Notify the unload intent so that all remaining shared pointers are
142     // released.
143     wallet->NotifyUnload();
144 
145     // Time to ditch our shared_ptr and wait for ReleaseWallet call.
146     wallet.reset();
147     {
148         WAIT_LOCK(g_wallet_release_mutex, lock);
149         while (g_unloading_wallet_set.count(name) == 1) {
150             g_wallet_release_cv.wait(lock);
151         }
152     }
153 }
154 
155 namespace {
LoadWalletInternal(interfaces::Chain & chain,const WalletLocation & location,std::string & error,std::vector<std::string> & warnings)156 std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
157 {
158     try {
159         if (!CWallet::Verify(chain, location, false, error, warnings)) {
160             error = "Wallet file verification failed: " + error;
161             return nullptr;
162         }
163 
164         std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings);
165         if (!wallet) {
166             error = "Wallet loading failed: " + error;
167             return nullptr;
168         }
169         AddWallet(wallet);
170         wallet->postInitProcess();
171         return wallet;
172     } catch (const std::runtime_error& e) {
173         error = e.what();
174         return nullptr;
175     }
176 }
177 } // namespace
178 
LoadWallet(interfaces::Chain & chain,const WalletLocation & location,std::string & error,std::vector<std::string> & warnings)179 std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
180 {
181     auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(location.GetName()));
182     if (!result.second) {
183         error = "Wallet already being loading.";
184         return nullptr;
185     }
186     auto wallet = LoadWalletInternal(chain, location, error, warnings);
187     WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
188     return wallet;
189 }
190 
LoadWallet(interfaces::Chain & chain,const std::string & name,std::string & error,std::vector<std::string> & warnings)191 std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
192 {
193     return LoadWallet(chain, WalletLocation(name), error, warnings);
194 }
195 
CreateWallet(interfaces::Chain & chain,const SecureString & passphrase,uint64_t wallet_creation_flags,const std::string & name,std::string & error,std::vector<std::string> & warnings,std::shared_ptr<CWallet> & result)196 WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result)
197 {
198     // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
199     bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
200 
201     // Born encrypted wallets need to be created blank first.
202     if (!passphrase.empty()) {
203         wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
204     }
205 
206     // Check the wallet file location
207     WalletLocation location(name);
208     if (location.Exists()) {
209         error = "Wallet " + location.GetName() + " already exists.";
210         return WalletCreationStatus::CREATION_FAILED;
211     }
212 
213     // Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
214     if (!CWallet::Verify(chain, location, false, error, warnings)) {
215         error = "Wallet file verification failed: " + error;
216         return WalletCreationStatus::CREATION_FAILED;
217     }
218 
219     // Do not allow a passphrase when private keys are disabled
220     if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
221         error = "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.";
222         return WalletCreationStatus::CREATION_FAILED;
223     }
224 
225     // Make the wallet
226     std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings, wallet_creation_flags);
227     if (!wallet) {
228         error = "Wallet creation failed: " + error;
229         return WalletCreationStatus::CREATION_FAILED;
230     }
231 
232     // Encrypt the wallet
233     if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
234         if (!wallet->EncryptWallet(passphrase)) {
235             error = "Error: Wallet created but failed to encrypt.";
236             return WalletCreationStatus::ENCRYPTION_FAILED;
237         }
238         if (!create_blank) {
239             // Unlock the wallet
240             if (!wallet->Unlock(passphrase)) {
241                 error = "Error: Wallet was encrypted but could not be unlocked";
242                 return WalletCreationStatus::ENCRYPTION_FAILED;
243             }
244 
245             // Set a seed for the wallet
246             {
247                 LOCK(wallet->cs_wallet);
248                 for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
249                     if (!spk_man->SetupGeneration()) {
250                         error = "Unable to generate initial keys";
251                         return WalletCreationStatus::CREATION_FAILED;
252                     }
253                 }
254             }
255 
256             // Relock the wallet
257             wallet->Lock();
258         }
259     }
260     AddWallet(wallet);
261     wallet->postInitProcess();
262     result = wallet;
263     return WalletCreationStatus::SUCCESS;
264 }
265 
266 const uint256 CWalletTx::ABANDON_HASH(UINT256_ONE());
267 
268 /** @defgroup mapWallet
269  *
270  * @{
271  */
272 
ToString() const273 std::string COutput::ToString() const
274 {
275     return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
276 }
277 
GetWalletTx(const uint256 & hash) const278 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
279 {
280     LOCK(cs_wallet);
281     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
282     if (it == mapWallet.end())
283         return nullptr;
284     return &(it->second);
285 }
286 
UpgradeKeyMetadata()287 void CWallet::UpgradeKeyMetadata()
288 {
289     if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
290         return;
291     }
292 
293     auto spk_man = GetLegacyScriptPubKeyMan();
294     if (!spk_man) {
295         return;
296     }
297 
298     spk_man->UpgradeKeyMetadata();
299     SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
300 }
301 
Unlock(const SecureString & strWalletPassphrase,bool accept_no_keys)302 bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
303 {
304     CCrypter crypter;
305     CKeyingMaterial _vMasterKey;
306 
307     {
308         LOCK(cs_wallet);
309         for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
310         {
311             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
312                 return false;
313             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
314                 continue; // try another master key
315             if (Unlock(_vMasterKey, accept_no_keys)) {
316                 // Now that we've unlocked, upgrade the key metadata
317                 UpgradeKeyMetadata();
318                 return true;
319             }
320         }
321     }
322     return false;
323 }
324 
ChangeWalletPassphrase(const SecureString & strOldWalletPassphrase,const SecureString & strNewWalletPassphrase)325 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
326 {
327     bool fWasLocked = IsLocked();
328 
329     {
330         LOCK(cs_wallet);
331         Lock();
332 
333         CCrypter crypter;
334         CKeyingMaterial _vMasterKey;
335         for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
336         {
337             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
338                 return false;
339             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
340                 return false;
341             if (Unlock(_vMasterKey))
342             {
343                 int64_t nStartTime = GetTimeMillis();
344                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
345                 pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
346 
347                 nStartTime = GetTimeMillis();
348                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
349                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
350 
351                 if (pMasterKey.second.nDeriveIterations < 25000)
352                     pMasterKey.second.nDeriveIterations = 25000;
353 
354                 WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
355 
356                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
357                     return false;
358                 if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
359                     return false;
360                 WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second);
361                 if (fWasLocked)
362                     Lock();
363                 return true;
364             }
365         }
366     }
367 
368     return false;
369 }
370 
chainStateFlushed(const CBlockLocator & loc)371 void CWallet::chainStateFlushed(const CBlockLocator& loc)
372 {
373     WalletBatch batch(*database);
374     batch.WriteBestBlock(loc);
375 }
376 
SetMinVersion(enum WalletFeature nVersion,WalletBatch * batch_in,bool fExplicit)377 void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
378 {
379     LOCK(cs_wallet);
380     if (nWalletVersion >= nVersion)
381         return;
382 
383     // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
384     if (fExplicit && nVersion > nWalletMaxVersion)
385             nVersion = FEATURE_LATEST;
386 
387     nWalletVersion = nVersion;
388 
389     if (nVersion > nWalletMaxVersion)
390         nWalletMaxVersion = nVersion;
391 
392     {
393         WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database);
394         if (nWalletVersion > 40000)
395             batch->WriteMinVersion(nWalletVersion);
396         if (!batch_in)
397             delete batch;
398     }
399 }
400 
SetMaxVersion(int nVersion)401 bool CWallet::SetMaxVersion(int nVersion)
402 {
403     LOCK(cs_wallet);
404     // cannot downgrade below current version
405     if (nWalletVersion > nVersion)
406         return false;
407 
408     nWalletMaxVersion = nVersion;
409 
410     return true;
411 }
412 
GetConflicts(const uint256 & txid) const413 std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
414 {
415     std::set<uint256> result;
416     AssertLockHeld(cs_wallet);
417 
418     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
419     if (it == mapWallet.end())
420         return result;
421     const CWalletTx& wtx = it->second;
422 
423     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
424 
425     for (const CTxIn& txin : wtx.tx->vin)
426     {
427         if (mapTxSpends.count(txin.prevout) <= 1)
428             continue;  // No conflict if zero or one spends
429         range = mapTxSpends.equal_range(txin.prevout);
430         for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
431             result.insert(_it->second);
432     }
433     return result;
434 }
435 
HasWalletSpend(const uint256 & txid) const436 bool CWallet::HasWalletSpend(const uint256& txid) const
437 {
438     AssertLockHeld(cs_wallet);
439     auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
440     return (iter != mapTxSpends.end() && iter->first.hash == txid);
441 }
442 
Flush(bool shutdown)443 void CWallet::Flush(bool shutdown)
444 {
445     if(shutdown)
446         StopStake();
447 
448     database->Flush(shutdown);
449 }
450 
SyncMetaData(std::pair<TxSpends::iterator,TxSpends::iterator> range)451 void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
452 {
453     // We want all the wallet transactions in range to have the same metadata as
454     // the oldest (smallest nOrderPos).
455     // So: find smallest nOrderPos:
456 
457     int nMinOrderPos = std::numeric_limits<int>::max();
458     const CWalletTx* copyFrom = nullptr;
459     for (TxSpends::iterator it = range.first; it != range.second; ++it) {
460         const CWalletTx* wtx = &mapWallet.at(it->second);
461         if (wtx->nOrderPos < nMinOrderPos) {
462             nMinOrderPos = wtx->nOrderPos;
463             copyFrom = wtx;
464         }
465     }
466 
467     if (!copyFrom) {
468         return;
469     }
470 
471     // Now copy data from copyFrom to rest:
472     for (TxSpends::iterator it = range.first; it != range.second; ++it)
473     {
474         const uint256& hash = it->second;
475         CWalletTx* copyTo = &mapWallet.at(hash);
476         if (copyFrom == copyTo) continue;
477         assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
478         if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
479         copyTo->mapValue = copyFrom->mapValue;
480         copyTo->vOrderForm = copyFrom->vOrderForm;
481         // fTimeReceivedIsTxTime not copied on purpose
482         // nTimeReceived not copied on purpose
483         copyTo->nTimeSmart = copyFrom->nTimeSmart;
484         copyTo->fFromMe = copyFrom->fFromMe;
485         // nOrderPos not copied on purpose
486         // cached members not copied on purpose
487     }
488 }
489 
490 /**
491  * Outpoint is spent if any non-conflicted transaction
492  * spends it:
493  */
IsSpent(const uint256 & hash,unsigned int n) const494 bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
495 {
496     const COutPoint outpoint(hash, n);
497     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
498     range = mapTxSpends.equal_range(outpoint);
499 
500     for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
501     {
502         const uint256& wtxid = it->second;
503         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
504         if (mit != mapWallet.end()) {
505             int depth = mit->second.GetDepthInMainChain();
506             if (depth > 0  || (depth == 0 && !mit->second.isAbandoned()))
507                 return true; // Spent
508         }
509     }
510     return false;
511 }
512 
AddToSpends(const COutPoint & outpoint,const uint256 & wtxid)513 void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
514 {
515     mapTxSpends.insert(std::make_pair(outpoint, wtxid));
516 
517     setLockedCoins.erase(outpoint);
518 
519     std::pair<TxSpends::iterator, TxSpends::iterator> range;
520     range = mapTxSpends.equal_range(outpoint);
521     SyncMetaData(range);
522 }
523 
RemoveFromSpends(const COutPoint & outpoint,const uint256 & wtxid)524 void CWallet::RemoveFromSpends(const COutPoint& outpoint, const uint256& wtxid)
525 {
526     std::pair<TxSpends::iterator, TxSpends::iterator> range;
527     range = mapTxSpends.equal_range(outpoint);
528     TxSpends::iterator it = range.first;
529     for(; it != range.second; ++ it)
530     {
531         if(it->second == wtxid)
532         {
533             mapTxSpends.erase(it);
534             break;
535         }
536     }
537     range = mapTxSpends.equal_range(outpoint);
538     if(range.first != range.second)
539         SyncMetaData(range);
540 }
541 
AddToSpends(const uint256 & wtxid)542 void CWallet::AddToSpends(const uint256& wtxid)
543 {
544     auto it = mapWallet.find(wtxid);
545     assert(it != mapWallet.end());
546     CWalletTx& thisTx = it->second;
547     if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
548         return;
549 
550     for (const CTxIn& txin : thisTx.tx->vin)
551         AddToSpends(txin.prevout, wtxid);
552 }
553 
RemoveFromSpends(const uint256 & wtxid)554 void CWallet::RemoveFromSpends(const uint256& wtxid)
555 {
556     assert(mapWallet.count(wtxid));
557     CWalletTx& thisTx = mapWallet.at(wtxid);
558 	if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
559         return;
560 
561     for(const CTxIn& txin : thisTx.tx->vin)
562         RemoveFromSpends(txin.prevout, wtxid);
563 }
564 
EncryptWallet(const SecureString & strWalletPassphrase)565 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
566 {
567     if (IsCrypted())
568         return false;
569 
570     CKeyingMaterial _vMasterKey;
571 
572     _vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
573     GetStrongRandBytes(&_vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
574 
575     CMasterKey kMasterKey;
576 
577     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
578     GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
579 
580     CCrypter crypter;
581     int64_t nStartTime = GetTimeMillis();
582     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
583     kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
584 
585     nStartTime = GetTimeMillis();
586     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
587     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
588 
589     if (kMasterKey.nDeriveIterations < 25000)
590         kMasterKey.nDeriveIterations = 25000;
591 
592     WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
593 
594     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
595         return false;
596     if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey))
597         return false;
598 
599     {
600         LOCK(cs_wallet);
601         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
602         WalletBatch* encrypted_batch = new WalletBatch(*database);
603         if (!encrypted_batch->TxnBegin()) {
604             delete encrypted_batch;
605             encrypted_batch = nullptr;
606             return false;
607         }
608         encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
609 
610         for (const auto& spk_man_pair : m_spk_managers) {
611             auto spk_man = spk_man_pair.second.get();
612             if (!spk_man->Encrypt(_vMasterKey, encrypted_batch)) {
613                 encrypted_batch->TxnAbort();
614                 delete encrypted_batch;
615                 encrypted_batch = nullptr;
616                 // We now probably have half of our keys encrypted in memory, and half not...
617                 // die and let the user reload the unencrypted wallet.
618                 assert(false);
619             }
620         }
621 
622         // Encryption was introduced in version 0.4.0
623         SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true);
624 
625         if (!encrypted_batch->TxnCommit()) {
626             delete encrypted_batch;
627             encrypted_batch = nullptr;
628             // We now have keys encrypted in memory, but not on disk...
629             // die to avoid confusion and let the user reload the unencrypted wallet.
630             assert(false);
631         }
632 
633         delete encrypted_batch;
634         encrypted_batch = nullptr;
635 
636         Lock();
637         Unlock(strWalletPassphrase);
638 
639         // if we are using HD, replace the HD seed with a new one
640         if (auto spk_man = GetLegacyScriptPubKeyMan()) {
641             if (spk_man->IsHDEnabled()) {
642                 if (!spk_man->SetupGeneration(true)) {
643                     return false;
644                 }
645             }
646         }
647         Lock();
648 
649         // Need to completely rewrite the wallet file; if we don't, bdb might keep
650         // bits of the unencrypted private key in slack space in the database file.
651         database->Rewrite();
652 
653         // BDB seems to have a bad habit of writing old data into
654         // slack space in .dat files; that is bad if the old data is
655         // unencrypted private keys. So:
656         database->ReloadDbEnv();
657 
658     }
659     NotifyStatusChanged(this);
660 
661     return true;
662 }
663 
ReorderTransactions()664 DBErrors CWallet::ReorderTransactions()
665 {
666     LOCK(cs_wallet);
667     WalletBatch batch(*database);
668 
669     // Old wallets didn't have any defined order for transactions
670     // Probably a bad idea to change the output of this
671 
672     // First: get all CWalletTx into a sorted-by-time multimap.
673     typedef std::multimap<int64_t, CWalletTx*> TxItems;
674     TxItems txByTime;
675 
676     for (auto& entry : mapWallet)
677     {
678         CWalletTx* wtx = &entry.second;
679         txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
680     }
681 
682     nOrderPosNext = 0;
683     std::vector<int64_t> nOrderPosOffsets;
684     for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
685     {
686         CWalletTx *const pwtx = (*it).second;
687         int64_t& nOrderPos = pwtx->nOrderPos;
688 
689         if (nOrderPos == -1)
690         {
691             nOrderPos = nOrderPosNext++;
692             nOrderPosOffsets.push_back(nOrderPos);
693 
694             if (!batch.WriteTx(*pwtx))
695                 return DBErrors::LOAD_FAIL;
696         }
697         else
698         {
699             int64_t nOrderPosOff = 0;
700             for (const int64_t& nOffsetStart : nOrderPosOffsets)
701             {
702                 if (nOrderPos >= nOffsetStart)
703                     ++nOrderPosOff;
704             }
705             nOrderPos += nOrderPosOff;
706             nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
707 
708             if (!nOrderPosOff)
709                 continue;
710 
711             // Since we're changing the order, write it back
712             if (!batch.WriteTx(*pwtx))
713                 return DBErrors::LOAD_FAIL;
714         }
715     }
716     batch.WriteOrderPosNext(nOrderPosNext);
717 
718     return DBErrors::LOAD_OK;
719 }
720 
IncOrderPosNext(WalletBatch * batch)721 int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
722 {
723     AssertLockHeld(cs_wallet);
724     int64_t nRet = nOrderPosNext++;
725     if (batch) {
726         batch->WriteOrderPosNext(nOrderPosNext);
727     } else {
728         WalletBatch(*database).WriteOrderPosNext(nOrderPosNext);
729     }
730     return nRet;
731 }
732 
MarkDirty()733 void CWallet::MarkDirty()
734 {
735     {
736         LOCK(cs_wallet);
737         for (std::pair<const uint256, CWalletTx>& item : mapWallet)
738             item.second.MarkDirty();
739     }
740 }
741 
MarkReplaced(const uint256 & originalHash,const uint256 & newHash)742 bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
743 {
744     LOCK(cs_wallet);
745 
746     auto mi = mapWallet.find(originalHash);
747 
748     // There is a bug if MarkReplaced is not called on an existing wallet transaction.
749     assert(mi != mapWallet.end());
750 
751     CWalletTx& wtx = (*mi).second;
752 
753     // Ensure for now that we're not overwriting data
754     assert(wtx.mapValue.count("replaced_by_txid") == 0);
755 
756     wtx.mapValue["replaced_by_txid"] = newHash.ToString();
757 
758     WalletBatch batch(*database, "r+");
759 
760     bool success = true;
761     if (!batch.WriteTx(wtx)) {
762         WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
763         success = false;
764     }
765 
766     NotifyTransactionChanged(this, originalHash, CT_UPDATED);
767 
768     return success;
769 }
770 
SetSpentKeyState(WalletBatch & batch,const uint256 & hash,unsigned int n,bool used,std::set<CTxDestination> & tx_destinations)771 void CWallet::SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
772 {
773     AssertLockHeld(cs_wallet);
774     const CWalletTx* srctx = GetWalletTx(hash);
775     if (!srctx) return;
776 
777     CTxDestination dst;
778     if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
779         if (IsMine(dst)) {
780             if (used && !GetDestData(dst, "used", nullptr)) {
781                 if (AddDestData(batch, dst, "used", "p")) { // p for "present", opposite of absent (null)
782                     tx_destinations.insert(dst);
783                 }
784             } else if (!used && GetDestData(dst, "used", nullptr)) {
785                 EraseDestData(batch, dst, "used");
786             }
787         }
788     }
789 }
790 
IsSpentKey(const uint256 & hash,unsigned int n) const791 bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
792 {
793     AssertLockHeld(cs_wallet);
794     CTxDestination dst;
795     const CWalletTx* srctx = GetWalletTx(hash);
796     if (srctx) {
797         assert(srctx->tx->vout.size() > n);
798         LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
799         // When descriptor wallets arrive, these additional checks are
800         // likely superfluous and can be optimized out
801         assert(spk_man != nullptr);
802         for (const auto& keyid : GetAffectedKeys(srctx->tx->vout[n].scriptPubKey, *spk_man)) {
803             WitnessV0KeyHash wpkh_dest(keyid);
804             if (GetDestData(wpkh_dest, "used", nullptr)) {
805                 return true;
806             }
807             ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
808             if (GetDestData(sh_wpkh_dest, "used", nullptr)) {
809                 return true;
810             }
811             PKHash pkh_dest(keyid);
812             if (GetDestData(pkh_dest, "used", nullptr)) {
813                 return true;
814             }
815         }
816     }
817     return false;
818 }
819 
AddToWallet(const CWalletTx & wtxIn,bool fFlushOnClose)820 bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
821 {
822     LOCK(cs_wallet);
823 
824     WalletBatch batch(*database, "r+", fFlushOnClose);
825 
826     uint256 hash = wtxIn.GetHash();
827 
828     if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
829         // Mark used destinations
830         std::set<CTxDestination> tx_destinations;
831 
832         for (const CTxIn& txin : wtxIn.tx->vin) {
833             const COutPoint& op = txin.prevout;
834             SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
835         }
836 
837         MarkDestinationsDirty(tx_destinations);
838     }
839 
840     // Inserts only if not already there, returns tx inserted or tx found
841     std::pair<std::map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(std::make_pair(hash, wtxIn));
842     CWalletTx& wtx = (*ret.first).second;
843     wtx.BindWallet(this);
844     bool fInsertedNew = ret.second;
845     if (fInsertedNew) {
846         wtx.nTimeReceived = chain().getAdjustedTime();
847         wtx.nOrderPos = IncOrderPosNext(&batch);
848         wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
849         wtx.nTimeSmart = ComputeTimeSmart(wtx);
850         AddToSpends(hash);
851     }
852 
853     bool fUpdated = false;
854     if (!fInsertedNew)
855     {
856         if (wtxIn.m_confirm.status != wtx.m_confirm.status) {
857             wtx.m_confirm.status = wtxIn.m_confirm.status;
858             wtx.m_confirm.nIndex = wtxIn.m_confirm.nIndex;
859             wtx.m_confirm.hashBlock = wtxIn.m_confirm.hashBlock;
860             wtx.m_confirm.block_height = wtxIn.m_confirm.block_height;
861             fUpdated = true;
862         } else {
863             assert(wtx.m_confirm.nIndex == wtxIn.m_confirm.nIndex);
864             assert(wtx.m_confirm.hashBlock == wtxIn.m_confirm.hashBlock);
865             assert(wtx.m_confirm.block_height == wtxIn.m_confirm.block_height);
866         }
867         if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
868         {
869             wtx.fFromMe = wtxIn.fFromMe;
870             fUpdated = true;
871         }
872         // If we have a witness-stripped version of this transaction, and we
873         // see a new version with a witness, then we must be upgrading a pre-segwit
874         // wallet.  Store the new version of the transaction with the witness,
875         // as the stripped-version must be invalid.
876         // TODO: Store all versions of the transaction, instead of just one.
877         if (wtxIn.tx->HasWitness() && !wtx.tx->HasWitness()) {
878             wtx.SetTx(wtxIn.tx);
879             fUpdated = true;
880         }
881         if(fUpdated && wtx.IsCoinStake())
882         {
883             AddToSpends(hash);
884         }
885     }
886 
887     // Update unspent addresses
888     if(fUpdateAddressUnspentCache)
889     {
890         std::map<COutPoint, CScriptCache> insertScriptCache;
891         for (unsigned int i = 0; i < wtxIn.tx->vout.size(); i++) {
892             isminetype mine = IsMine(wtxIn.tx->vout[i]);
893             if (!(IsSpent(hash, i)) && mine != ISMINE_NO &&
894                 !IsLockedCoin(hash, i) && (wtxIn.tx->vout[i].nValue > 0) &&
895                 // Check if the staking coin is dust
896                 wtxIn.tx->vout[i].nValue >= m_staker_min_utxo_size)
897             {
898                 // Get the script data for the coin
899                 COutPoint prevout = COutPoint(hash, i);
900                 const CScriptCache& scriptCache = GetScriptCache(prevout, wtxIn.tx->vout[i].scriptPubKey, &insertScriptCache);
901 
902                 // Check that the script is not a contract script
903                 if(scriptCache.contract || !scriptCache.keyIdOk)
904                     continue;
905 
906                 if(mapAddressUnspentCache.find(scriptCache.keyId) == mapAddressUnspentCache.end())
907                 {
908                     mapAddressUnspentCache[scriptCache.keyId] = true;
909                 }
910             }
911         }
912     }
913 
914     //// debug print
915     WalletLogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
916 
917     // Write to disk
918     if (fInsertedNew || fUpdated)
919         if (!batch.WriteTx(wtx))
920             return false;
921 
922     // Break debit/credit balance caches:
923     wtx.MarkDirty();
924 
925     // Notify UI of new or updated transaction
926     NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
927 
928 #if HAVE_SYSTEM
929     // notify an external script when a wallet transaction comes in or is updated
930     std::string strCmd = gArgs.GetArg("-walletnotify", "");
931 
932     if (!strCmd.empty())
933     {
934         boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
935 #ifndef WIN32
936         // Substituting the wallet name isn't currently supported on windows
937         // because windows shell escaping has not been implemented yet:
938         // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
939         // A few ways it could be implemented in the future are described in:
940         // https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
941         boost::replace_all(strCmd, "%w", ShellEscape(GetName()));
942 #endif
943         std::thread t(runCommand, strCmd);
944         t.detach(); // thread runs free
945     }
946 #endif
947 
948     return true;
949 }
950 
LoadToWallet(CWalletTx & wtxIn)951 void CWallet::LoadToWallet(CWalletTx& wtxIn)
952 {
953     // If wallet doesn't have a chain (e.g bitcoin-wallet), lock can't be taken.
954     auto locked_chain = LockChain();
955     if (locked_chain) {
956         Optional<int> block_height = locked_chain->getBlockHeight(wtxIn.m_confirm.hashBlock);
957         if (block_height) {
958             // Update cached block height variable since it not stored in the
959             // serialized transaction.
960             wtxIn.m_confirm.block_height = *block_height;
961         } else if (wtxIn.isConflicted() || wtxIn.isConfirmed()) {
962             // If tx block (or conflicting block) was reorged out of chain
963             // while the wallet was shutdown, change tx status to UNCONFIRMED
964             // and reset block height, hash, and index. ABANDONED tx don't have
965             // associated blocks and don't need to be updated. The case where a
966             // transaction was reorged out while online and then reconfirmed
967             // while offline is covered by the rescan logic.
968             wtxIn.setUnconfirmed();
969             wtxIn.m_confirm.hashBlock = uint256();
970             wtxIn.m_confirm.block_height = 0;
971             wtxIn.m_confirm.nIndex = 0;
972         }
973     }
974     uint256 hash = wtxIn.GetHash();
975     const auto& ins = mapWallet.emplace(hash, wtxIn);
976     CWalletTx& wtx = ins.first->second;
977     wtx.BindWallet(this);
978     if (/* insertion took place */ ins.second) {
979         wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
980     }
981     AddToSpends(hash);
982     for (const CTxIn& txin : wtx.tx->vin) {
983         auto it = mapWallet.find(txin.prevout.hash);
984         if (it != mapWallet.end()) {
985             CWalletTx& prevtx = it->second;
986             if (prevtx.isConflicted()) {
987                 MarkConflicted(prevtx.m_confirm.hashBlock, prevtx.m_confirm.block_height, wtx.GetHash());
988             }
989         }
990     }
991 }
992 
AddToWalletIfInvolvingMe(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool fUpdate)993 bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate)
994 {
995     const CTransaction& tx = *ptx;
996     {
997         AssertLockHeld(cs_wallet);
998 
999         if (!confirm.hashBlock.IsNull()) {
1000             for (const CTxIn& txin : tx.vin) {
1001                 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1002                 while (range.first != range.second) {
1003                     if (range.first->second != tx.GetHash()) {
1004                         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);
1005                         MarkConflicted(confirm.hashBlock, confirm.block_height, range.first->second);
1006                     }
1007                     range.first++;
1008                 }
1009             }
1010         }
1011 
1012         bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1013         if (fExisted && !fUpdate) return false;
1014         if (fExisted || IsMine(tx) || IsFromMe(tx))
1015         {
1016             /* Check if any keys in the wallet keypool that were supposed to be unused
1017              * have appeared in a new transaction. If so, remove those keys from the keypool.
1018              * This can happen when restoring an old wallet backup that does not contain
1019              * the mostly recently created transactions from newer versions of the wallet.
1020              */
1021 
1022             // loop though all outputs
1023             for (const CTxOut& txout: tx.vout) {
1024                 for (const auto& spk_man_pair : m_spk_managers) {
1025                     spk_man_pair.second->MarkUnusedAddresses(txout.scriptPubKey);
1026                 }
1027             }
1028 
1029             CWalletTx wtx(this, ptx);
1030 
1031             // Block disconnection override an abandoned tx as unconfirmed
1032             // which means user may have to call abandontransaction again
1033             wtx.m_confirm = confirm;
1034 
1035             return AddToWallet(wtx, false);
1036         }
1037     }
1038     return false;
1039 }
1040 
TransactionCanBeAbandoned(const uint256 & hashTx) const1041 bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
1042 {
1043     auto locked_chain = chain().lock();
1044     LOCK(cs_wallet);
1045     const CWalletTx* wtx = GetWalletTx(hashTx);
1046     return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
1047 }
1048 
MarkInputsDirty(const CTransactionRef & tx)1049 void CWallet::MarkInputsDirty(const CTransactionRef& tx)
1050 {
1051     for (const CTxIn& txin : tx->vin) {
1052         auto it = mapWallet.find(txin.prevout.hash);
1053         if (it != mapWallet.end()) {
1054             it->second.MarkDirty();
1055         }
1056     }
1057 }
1058 
AbandonTransaction(const uint256 & hashTx)1059 bool CWallet::AbandonTransaction(const uint256& hashTx)
1060 {
1061     auto locked_chain = chain().lock(); // Temporary. Removed in upcoming lock cleanup
1062     LOCK(cs_wallet);
1063 
1064     WalletBatch batch(*database, "r+");
1065 
1066     std::set<uint256> todo;
1067     std::set<uint256> done;
1068 
1069     // Can't mark abandoned if confirmed or in mempool
1070     auto it = mapWallet.find(hashTx);
1071     assert(it != mapWallet.end());
1072     CWalletTx& origtx = it->second;
1073     if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1074         return false;
1075     }
1076 
1077     todo.insert(hashTx);
1078 
1079     while (!todo.empty()) {
1080         uint256 now = *todo.begin();
1081         todo.erase(now);
1082         done.insert(now);
1083         auto it = mapWallet.find(now);
1084         assert(it != mapWallet.end());
1085         CWalletTx& wtx = it->second;
1086         int currentconfirm = wtx.GetDepthInMainChain();
1087         // If the orig tx was not in block, none of its spends can be
1088         assert(currentconfirm <= 0);
1089         // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
1090         if (currentconfirm == 0 && !wtx.isAbandoned()) {
1091             // If the orig tx was not in block/mempool, none of its spends can be in mempool
1092             assert(!wtx.InMempool());
1093             wtx.setAbandoned();
1094             wtx.MarkDirty();
1095             batch.WriteTx(wtx);
1096             NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED);
1097             // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
1098             TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1099             while (iter != mapTxSpends.end() && iter->first.hash == now) {
1100                 if (!done.count(iter->second)) {
1101                     todo.insert(iter->second);
1102                 }
1103                 iter++;
1104             }
1105             // If a transaction changes 'conflicted' state, that changes the balance
1106             // available of the outputs it spends. So force those to be recomputed
1107             MarkInputsDirty(wtx.tx);
1108         }
1109     }
1110 
1111     return true;
1112 }
1113 
MarkConflicted(const uint256 & hashBlock,int conflicting_height,const uint256 & hashTx)1114 void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1115 {
1116     auto locked_chain = chain().lock();
1117     LOCK(cs_wallet);
1118 
1119     int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1120     // If number of conflict confirms cannot be determined, this means
1121     // that the block is still unknown or not yet part of the main chain,
1122     // for example when loading the wallet during a reindex. Do nothing in that
1123     // case.
1124     if (conflictconfirms >= 0)
1125         return;
1126 
1127     // Do not flush the wallet here for performance reasons
1128     WalletBatch batch(*database, "r+", false);
1129 
1130     std::set<uint256> todo;
1131     std::set<uint256> done;
1132 
1133     todo.insert(hashTx);
1134 
1135     while (!todo.empty()) {
1136         uint256 now = *todo.begin();
1137         todo.erase(now);
1138         done.insert(now);
1139         auto it = mapWallet.find(now);
1140         assert(it != mapWallet.end());
1141         CWalletTx& wtx = it->second;
1142         int currentconfirm = wtx.GetDepthInMainChain();
1143         if (conflictconfirms < currentconfirm) {
1144             // Block is 'more conflicted' than current confirm; update.
1145             // Mark transaction as conflicted with this block.
1146             wtx.m_confirm.nIndex = 0;
1147             wtx.m_confirm.hashBlock = hashBlock;
1148             wtx.m_confirm.block_height = conflicting_height;
1149             wtx.setConflicted();
1150             wtx.MarkDirty();
1151             batch.WriteTx(wtx);
1152             // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
1153             TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1154             while (iter != mapTxSpends.end() && iter->first.hash == now) {
1155                  if (!done.count(iter->second)) {
1156                      todo.insert(iter->second);
1157                  }
1158                  iter++;
1159             }
1160             // If a transaction changes 'conflicted' state, that changes the balance
1161             // available of the outputs it spends. So force those to be recomputed
1162             MarkInputsDirty(wtx.tx);
1163         }
1164     }
1165 }
1166 
SyncTransaction(const CTransactionRef & ptx,CWalletTx::Confirmation confirm,bool update_tx)1167 void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx)
1168 {
1169     if (confirm.hashBlock.IsNull() && confirm.nIndex == -1)
1170     {
1171         // wallets need to refund inputs when disconnecting coinstake
1172         const CTransaction& tx = *ptx;
1173         if (tx.IsCoinStake() && IsFromMe(tx))
1174         {
1175             DisableTransaction(tx);
1176             return;
1177         }
1178     }
1179 
1180     if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
1181         return; // Not one of ours
1182 
1183     // If a transaction changes 'conflicted' state, that changes the balance
1184     // available of the outputs it spends. So force those to be
1185     // recomputed, also:
1186     MarkInputsDirty(ptx);
1187 }
1188 
transactionAddedToMempool(const CTransactionRef & tx)1189 void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
1190     LOCK(cs_wallet);
1191     SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1192 
1193     auto it = mapWallet.find(tx->GetHash());
1194     if (it != mapWallet.end()) {
1195         it->second.fInMempool = true;
1196     }
1197 }
1198 
transactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason)1199 void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {
1200     LOCK(cs_wallet);
1201     auto it = mapWallet.find(tx->GetHash());
1202     if (it != mapWallet.end()) {
1203         it->second.fInMempool = false;
1204     }
1205     // Handle transactions that were removed from the mempool because they
1206     // conflict with transactions in a newly connected block.
1207     if (reason == MemPoolRemovalReason::CONFLICT) {
1208         // Call SyncNotifications, so external -walletnotify notifications will
1209         // be triggered for these transactions. Set Status::UNCONFIRMED instead
1210         // of Status::CONFLICTED for a few reasons:
1211         //
1212         // 1. The transactionRemovedFromMempool callback does not currently
1213         //    provide the conflicting block's hash and height, and for backwards
1214         //    compatibility reasons it may not be not safe to store conflicted
1215         //    wallet transactions with a null block hash. See
1216         //    https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1217         // 2. For most of these transactions, the wallet's internal conflict
1218         //    detection in the blockConnected handler will subsequently call
1219         //    MarkConflicted and update them with CONFLICTED status anyway. This
1220         //    applies to any wallet transaction that has inputs spent in the
1221         //    block, or that has ancestors in the wallet with inputs spent by
1222         //    the block.
1223         // 3. Longstanding behavior since the sync implementation in
1224         //    https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1225         //    implementation before that was to mark these transactions
1226         //    unconfirmed rather than conflicted.
1227         //
1228         // Nothing described above should be seen as an unchangeable requirement
1229         // when improving this code in the future. The wallet's heuristics for
1230         // distinguishing between conflicted and unconfirmed transactions are
1231         // imperfect, and could be improved in general, see
1232         // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1233         SyncTransaction(tx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1234     }
1235 }
1236 
blockConnected(const CBlock & block,int height)1237 void CWallet::blockConnected(const CBlock& block, int height)
1238 {
1239     const uint256& block_hash = block.GetHash();
1240     auto locked_chain = chain().lock();
1241     LOCK(cs_wallet);
1242 
1243     m_last_block_processed_height = height;
1244     m_last_block_processed = block_hash;
1245     for (size_t index = 0; index < block.vtx.size(); index++) {
1246         SyncTransaction(block.vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
1247         transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK);
1248     }
1249 }
1250 
blockDisconnected(const CBlock & block,int height)1251 void CWallet::blockDisconnected(const CBlock& block, int height)
1252 {
1253     auto locked_chain = chain().lock();
1254     LOCK(cs_wallet);
1255 
1256     // At block disconnection, this will change an abandoned transaction to
1257     // be unconfirmed, whether or not the transaction is added back to the mempool.
1258     // User may have to call abandontransaction again. It may be addressed in the
1259     // future with a stickier abandoned state or even removing abandontransaction call.
1260     m_last_block_processed_height = height - 1;
1261     m_last_block_processed = block.hashPrevBlock;
1262     for (const CTransactionRef& ptx : block.vtx) {
1263         int index = ptx->IsCoinStake() ? -1 : 0;
1264         SyncTransaction(ptx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, index});
1265     }
1266 }
1267 
updatedBlockTip()1268 void CWallet::updatedBlockTip()
1269 {
1270     m_best_block_time = GetTime();
1271 }
1272 
1273 
BlockUntilSyncedToCurrentChain() const1274 void CWallet::BlockUntilSyncedToCurrentChain() const {
1275     AssertLockNotHeld(cs_wallet);
1276     // Skip the queue-draining stuff if we know we're caught up with
1277     // ::ChainActive().Tip(), otherwise put a callback in the validation interface queue and wait
1278     // for the queue to drain enough to execute it (indicating we are caught up
1279     // at least with the time we entered this function).
1280     uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1281     chain().waitForNotificationsIfTipChanged(last_block_hash);
1282 }
1283 
1284 
IsMine(const CTxIn & txin) const1285 isminetype CWallet::IsMine(const CTxIn &txin) const
1286 {
1287     {
1288         LOCK(cs_wallet);
1289         std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1290         if (mi != mapWallet.end())
1291         {
1292             const CWalletTx& prev = (*mi).second;
1293             if (txin.prevout.n < prev.tx->vout.size())
1294                 return IsMine(prev.tx->vout[txin.prevout.n]);
1295         }
1296     }
1297     return ISMINE_NO;
1298 }
1299 
1300 // Note that this function doesn't distinguish between a 0-valued input,
1301 // and a not-"is mine" (according to the filter) input.
GetDebit(const CTxIn & txin,const isminefilter & filter) const1302 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
1303 {
1304     {
1305         LOCK(cs_wallet);
1306         std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1307         if (mi != mapWallet.end())
1308         {
1309             const CWalletTx& prev = (*mi).second;
1310             if (txin.prevout.n < prev.tx->vout.size())
1311                 if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1312                     return prev.tx->vout[txin.prevout.n].nValue;
1313         }
1314     }
1315     return 0;
1316 }
1317 
IsMine(const CTxOut & txout) const1318 isminetype CWallet::IsMine(const CTxOut& txout) const
1319 {
1320     return IsMine(txout.scriptPubKey);
1321 }
1322 
IsMine(const CTxDestination & dest) const1323 isminetype CWallet::IsMine(const CTxDestination& dest) const
1324 {
1325     return IsMine(GetScriptForDestination(dest));
1326 }
1327 
IsMine(const CScript & script) const1328 isminetype CWallet::IsMine(const CScript& script) const
1329 {
1330     isminetype result = ISMINE_NO;
1331     for (const auto& spk_man_pair : m_spk_managers) {
1332         result = std::max(result, spk_man_pair.second->IsMine(script));
1333     }
1334     return result;
1335 }
1336 
GetCredit(const CTxOut & txout,const isminefilter & filter) const1337 CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
1338 {
1339     if (!MoneyRange(txout.nValue))
1340         throw std::runtime_error(std::string(__func__) + ": value out of range");
1341     return ((IsMine(txout) & filter) ? txout.nValue : 0);
1342 }
1343 
IsChange(const CTxOut & txout) const1344 bool CWallet::IsChange(const CTxOut& txout) const
1345 {
1346     return IsChange(txout.scriptPubKey);
1347 }
1348 
IsChange(const CScript & script) const1349 bool CWallet::IsChange(const CScript& script) const
1350 {
1351     // TODO: fix handling of 'change' outputs. The assumption is that any
1352     // payment to a script that is ours, but is not in the address book
1353     // is change. That assumption is likely to break when we implement multisignature
1354     // wallets that return change back into a multi-signature-protected address;
1355     // a better way of identifying which outputs are 'the send' and which are
1356     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
1357     // which output, if any, was change).
1358     if (IsMine(script))
1359     {
1360         CTxDestination address;
1361         if (!ExtractDestination(script, address))
1362             return true;
1363 
1364         LOCK(cs_wallet);
1365         if (!FindAddressBookEntry(address)) {
1366             return true;
1367         }
1368     }
1369     return false;
1370 }
1371 
GetChange(const CTxOut & txout) const1372 CAmount CWallet::GetChange(const CTxOut& txout) const
1373 {
1374     if (!MoneyRange(txout.nValue))
1375         throw std::runtime_error(std::string(__func__) + ": value out of range");
1376     return (IsChange(txout) ? txout.nValue : 0);
1377 }
1378 
IsMine(const CTransaction & tx) const1379 bool CWallet::IsMine(const CTransaction& tx) const
1380 {
1381     for (const CTxOut& txout : tx.vout)
1382         if (IsMine(txout))
1383             return true;
1384     return false;
1385 }
1386 
IsFromMe(const CTransaction & tx) const1387 bool CWallet::IsFromMe(const CTransaction& tx) const
1388 {
1389     return (GetDebit(tx, ISMINE_ALL) > 0);
1390 }
1391 
GetDebit(const CTransaction & tx,const isminefilter & filter) const1392 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1393 {
1394     CAmount nDebit = 0;
1395     for (const CTxIn& txin : tx.vin)
1396     {
1397         nDebit += GetDebit(txin, filter);
1398         if (!MoneyRange(nDebit))
1399             throw std::runtime_error(std::string(__func__) + ": value out of range");
1400     }
1401     return nDebit;
1402 }
1403 
IsAllFromMe(const CTransaction & tx,const isminefilter & filter) const1404 bool CWallet::IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const
1405 {
1406     LOCK(cs_wallet);
1407 
1408     for (const CTxIn& txin : tx.vin)
1409     {
1410         auto mi = mapWallet.find(txin.prevout.hash);
1411         if (mi == mapWallet.end())
1412             return false; // any unknown inputs can't be from us
1413 
1414         const CWalletTx& prev = (*mi).second;
1415 
1416         if (txin.prevout.n >= prev.tx->vout.size())
1417             return false; // invalid input!
1418 
1419         if (!(IsMine(prev.tx->vout[txin.prevout.n]) & filter))
1420             return false;
1421     }
1422     return true;
1423 }
1424 
GetCredit(const CTransaction & tx,const isminefilter & filter) const1425 CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const
1426 {
1427     CAmount nCredit = 0;
1428     for (const CTxOut& txout : tx.vout)
1429     {
1430         nCredit += GetCredit(txout, filter);
1431         if (!MoneyRange(nCredit))
1432             throw std::runtime_error(std::string(__func__) + ": value out of range");
1433     }
1434     return nCredit;
1435 }
1436 
GetChange(const CTransaction & tx) const1437 CAmount CWallet::GetChange(const CTransaction& tx) const
1438 {
1439     CAmount nChange = 0;
1440     for (const CTxOut& txout : tx.vout)
1441     {
1442         nChange += GetChange(txout);
1443         if (!MoneyRange(nChange))
1444             throw std::runtime_error(std::string(__func__) + ": value out of range");
1445     }
1446     return nChange;
1447 }
1448 
IsHDEnabled() const1449 bool CWallet::IsHDEnabled() const
1450 {
1451     bool result = true;
1452     for (const auto& spk_man_pair : m_spk_managers) {
1453         result &= spk_man_pair.second->IsHDEnabled();
1454     }
1455     return result;
1456 }
1457 
CanGetAddresses(bool internal) const1458 bool CWallet::CanGetAddresses(bool internal) const
1459 {
1460     LOCK(cs_wallet);
1461     if (m_spk_managers.empty()) return false;
1462     for (OutputType t : OUTPUT_TYPES) {
1463         auto spk_man = GetScriptPubKeyMan(t, internal);
1464         if (spk_man && spk_man->CanGetAddresses(internal)) {
1465             return true;
1466         }
1467     }
1468     return false;
1469 }
1470 
SetWalletFlag(uint64_t flags)1471 void CWallet::SetWalletFlag(uint64_t flags)
1472 {
1473     LOCK(cs_wallet);
1474     m_wallet_flags |= flags;
1475     if (!WalletBatch(*database).WriteWalletFlags(m_wallet_flags))
1476         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1477 }
1478 
UnsetWalletFlag(uint64_t flag)1479 void CWallet::UnsetWalletFlag(uint64_t flag)
1480 {
1481     WalletBatch batch(*database);
1482     UnsetWalletFlagWithDB(batch, flag);
1483 }
1484 
UnsetWalletFlagWithDB(WalletBatch & batch,uint64_t flag)1485 void CWallet::UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag)
1486 {
1487     LOCK(cs_wallet);
1488     m_wallet_flags &= ~flag;
1489     if (!batch.WriteWalletFlags(m_wallet_flags))
1490         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1491 }
1492 
UnsetBlankWalletFlag(WalletBatch & batch)1493 void CWallet::UnsetBlankWalletFlag(WalletBatch& batch)
1494 {
1495     UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
1496 }
1497 
IsWalletFlagSet(uint64_t flag) const1498 bool CWallet::IsWalletFlagSet(uint64_t flag) const
1499 {
1500     return (m_wallet_flags & flag);
1501 }
1502 
SetWalletFlags(uint64_t overwriteFlags,bool memonly)1503 bool CWallet::SetWalletFlags(uint64_t overwriteFlags, bool memonly)
1504 {
1505     LOCK(cs_wallet);
1506     m_wallet_flags = overwriteFlags;
1507     if (((overwriteFlags & KNOWN_WALLET_FLAGS) >> 32) ^ (overwriteFlags >> 32)) {
1508         // contains unknown non-tolerable wallet flags
1509         return false;
1510     }
1511     if (!memonly && !WalletBatch(*database).WriteWalletFlags(m_wallet_flags)) {
1512         throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
1513     }
1514 
1515     return true;
1516 }
1517 
GetTxTime() const1518 int64_t CWalletTx::GetTxTime() const
1519 {
1520     int64_t n = nTimeSmart;
1521     return n ? n : nTimeReceived;
1522 }
1523 
1524 // Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1525 // 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) const1526 bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
1527 {
1528     // Fill in dummy signatures for fee calculation.
1529     const CScript& scriptPubKey = txout.scriptPubKey;
1530     SignatureData sigdata;
1531 
1532     std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
1533     if (!provider) {
1534         // We don't know about this scriptpbuKey;
1535         return false;
1536     }
1537 
1538     if (!ProduceSignature(*provider, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
1539         return false;
1540     }
1541     UpdateInput(tx_in, sigdata);
1542     return true;
1543 }
1544 
1545 // 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) const1546 bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
1547 {
1548     // Fill in dummy signatures for fee calculation.
1549     int nIn = 0;
1550     for (const auto& txout : txouts)
1551     {
1552         if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
1553             return false;
1554         }
1555 
1556         nIn++;
1557     }
1558     return true;
1559 }
1560 
ImportScripts(const std::set<CScript> scripts,int64_t timestamp)1561 bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
1562 {
1563     auto spk_man = GetLegacyScriptPubKeyMan();
1564     if (!spk_man) {
1565         return false;
1566     }
1567     LOCK(spk_man->cs_KeyStore);
1568     return spk_man->ImportScripts(scripts, timestamp);
1569 }
1570 
ImportPrivKeys(const std::map<CKeyID,CKey> & privkey_map,const int64_t timestamp)1571 bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
1572 {
1573     auto spk_man = GetLegacyScriptPubKeyMan();
1574     if (!spk_man) {
1575         return false;
1576     }
1577     LOCK(spk_man->cs_KeyStore);
1578     return spk_man->ImportPrivKeys(privkey_map, timestamp);
1579 }
1580 
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)1581 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)
1582 {
1583     auto spk_man = GetLegacyScriptPubKeyMan();
1584     if (!spk_man) {
1585         return false;
1586     }
1587     LOCK(spk_man->cs_KeyStore);
1588     return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, internal, timestamp);
1589 }
1590 
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)1591 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)
1592 {
1593     auto spk_man = GetLegacyScriptPubKeyMan();
1594     if (!spk_man) {
1595         return false;
1596     }
1597     LOCK(spk_man->cs_KeyStore);
1598     if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
1599         return false;
1600     }
1601     if (apply_label) {
1602         WalletBatch batch(*database);
1603         for (const CScript& script : script_pub_keys) {
1604             CTxDestination dest;
1605             ExtractDestination(script, dest);
1606             if (IsValidDestination(dest)) {
1607                 SetAddressBookWithDB(batch, dest, label, "receive");
1608             }
1609         }
1610     }
1611     return true;
1612 }
1613 
CalculateMaximumSignedTxSize(const CTransaction & tx,const CWallet * wallet,bool use_max_sig)1614 int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
1615 {
1616     std::vector<CTxOut> txouts;
1617     for (const CTxIn& input : tx.vin) {
1618         const auto mi = wallet->mapWallet.find(input.prevout.hash);
1619         // Can not estimate size without knowing the input details
1620         if (mi == wallet->mapWallet.end()) {
1621             return -1;
1622         }
1623         assert(input.prevout.n < mi->second.tx->vout.size());
1624         txouts.emplace_back(mi->second.tx->vout[input.prevout.n]);
1625     }
1626     return CalculateMaximumSignedTxSize(tx, wallet, txouts, use_max_sig);
1627 }
1628 
1629 // txouts needs to be in the order of tx.vin
CalculateMaximumSignedTxSize(const CTransaction & tx,const CWallet * wallet,const std::vector<CTxOut> & txouts,bool use_max_sig)1630 int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
1631 {
1632     CMutableTransaction txNew(tx);
1633     if (!wallet->DummySignTx(txNew, txouts, use_max_sig)) {
1634         return -1;
1635     }
1636     return GetVirtualTransactionSize(CTransaction(txNew));
1637 }
1638 
CalculateMaximumSignedInputSize(const CTxOut & txout,const CWallet * wallet,bool use_max_sig)1639 int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
1640 {
1641     CMutableTransaction txn;
1642     txn.vin.push_back(CTxIn(COutPoint()));
1643     if (!wallet->DummySignInput(txn.vin[0], txout, use_max_sig)) {
1644         return -1;
1645     }
1646     return GetVirtualTransactionInputSize(txn.vin[0]);
1647 }
1648 
GetAmounts(std::list<COutputEntry> & listReceived,std::list<COutputEntry> & listSent,CAmount & nFee,const isminefilter & filter) const1649 void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
1650                            std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const
1651 {
1652     nFee = 0;
1653     listReceived.clear();
1654     listSent.clear();
1655 
1656     // Compute fee:
1657     CAmount nDebit = GetDebit(filter);
1658     if (nDebit > 0) // debit>0 means we signed/sent this transaction
1659     {
1660         CAmount nValueOut = tx->GetValueOut();
1661         nFee = nDebit - nValueOut;
1662     }
1663 
1664     // Sent/received.
1665     for (unsigned int i = 0; i < tx->vout.size(); ++i)
1666     {
1667         const CTxOut& txout = tx->vout[i];
1668         isminetype fIsMine = pwallet->IsMine(txout);
1669         // Only need to handle txouts if AT LEAST one of these is true:
1670         //   1) they debit from us (sent)
1671         //   2) the output is to us (received)
1672         if (nDebit > 0)
1673         {
1674             // Don't report 'change' txouts
1675             if (pwallet->IsChange(txout))
1676                 continue;
1677         }
1678         else if (!(fIsMine & filter))
1679             continue;
1680 
1681         // In either case, we need to get the destination address
1682         CTxDestination address;
1683 
1684         if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
1685         {
1686             pwallet->WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
1687                                     this->GetHash().ToString());
1688             address = CNoDestination();
1689         }
1690 
1691         COutputEntry output = {address, txout.nValue, (int)i};
1692 
1693         // If we are debited by the transaction, add the output as a "sent" entry
1694         if (nDebit > 0)
1695             listSent.push_back(output);
1696 
1697         // If we are receiving the output, add it as a "received" entry
1698         if (fIsMine & filter)
1699             listReceived.push_back(output);
1700     }
1701 
1702 }
1703 
1704 /**
1705  * Scan active chain for relevant transactions after importing keys. This should
1706  * be called whenever new keys are added to the wallet, with the oldest key
1707  * creation time.
1708  *
1709  * @return Earliest timestamp that could be successfully scanned from. Timestamp
1710  * returned will be higher than startTime if relevant blocks could not be read.
1711  */
RescanFromTime(int64_t startTime,const WalletRescanReserver & reserver,bool update)1712 int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1713 {
1714     // Find starting block. May be null if nCreateTime is greater than the
1715     // highest blockchain timestamp, in which case there is nothing that needs
1716     // to be scanned.
1717     uint256 start_block;
1718     {
1719         auto locked_chain = chain().lock();
1720         const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
1721         const Optional<int> tip_height = locked_chain->getHeight();
1722         WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
1723     }
1724 
1725     if (!start_block.IsNull()) {
1726         // TODO: this should take into account failure by ScanResult::USER_ABORT
1727         ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
1728         if (result.status == ScanResult::FAILURE) {
1729             int64_t time_max;
1730             if (!chain().findBlock(result.last_failed_block, nullptr /* block */, nullptr /* time */, &time_max)) {
1731                 throw std::logic_error("ScanForWalletTransactions returned invalid block hash");
1732             }
1733             return time_max + TIMESTAMP_WINDOW + 1;
1734         }
1735     }
1736     return startTime;
1737 }
1738 
1739 /**
1740  * Scan the block chain (starting in start_block) for transactions
1741  * from or to us. If fUpdate is true, found transactions that already
1742  * exist in the wallet will be updated.
1743  *
1744  * @param[in] start_block Scan starting block. If block is not on the active
1745  *                        chain, the scan will return SUCCESS immediately.
1746  * @param[in] stop_block  Scan ending block. If block is not on the active
1747  *                        chain, the scan will continue until it reaches the
1748  *                        chain tip.
1749  *
1750  * @return ScanResult returning scan information and indicating success or
1751  *         failure. Return status will be set to SUCCESS if scan was
1752  *         successful. FAILURE if a complete rescan was not possible (due to
1753  *         pruning or corruption). USER_ABORT if the rescan was aborted before
1754  *         it could complete.
1755  *
1756  * @pre Caller needs to make sure start_block (and the optional stop_block) are on
1757  * the main chain after to the addition of any new keys you want to detect
1758  * transactions for.
1759  */
ScanForWalletTransactions(const uint256 & start_block,const uint256 & stop_block,const WalletRescanReserver & reserver,bool fUpdate)1760 CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver& reserver, bool fUpdate)
1761 {
1762     int64_t nNow = GetTime();
1763     int64_t start_time = GetTimeMillis();
1764 
1765     assert(reserver.isReserved());
1766 
1767     uint256 block_hash = start_block;
1768     ScanResult result;
1769 
1770     WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
1771 
1772     fAbortRescan = false;
1773     ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
1774     uint256 tip_hash;
1775     // The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
1776     Optional<int> block_height = MakeOptional(false, int());
1777     double progress_begin;
1778     double progress_end;
1779     {
1780         auto locked_chain = chain().lock();
1781         if (Optional<int> tip_height = locked_chain->getHeight()) {
1782             tip_hash = locked_chain->getBlockHash(*tip_height);
1783         }
1784         block_height = locked_chain->getBlockHeight(block_hash);
1785         progress_begin = chain().guessVerificationProgress(block_hash);
1786         progress_end = chain().guessVerificationProgress(stop_block.IsNull() ? tip_hash : stop_block);
1787     }
1788     double progress_current = progress_begin;
1789     while (block_height && !fAbortRescan && !chain().shutdownRequested()) {
1790         m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1791         if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
1792             ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
1793         }
1794         if (GetTime() >= nNow + 60) {
1795             nNow = GetTime();
1796             WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", *block_height, progress_current);
1797         }
1798 
1799         CBlock block;
1800         if (chain().findBlock(block_hash, &block) && !block.IsNull()) {
1801             auto locked_chain = chain().lock();
1802             LOCK(cs_wallet);
1803             if (!locked_chain->getBlockHeight(block_hash)) {
1804                 // Abort scan if current block is no longer active, to prevent
1805                 // marking transactions as coming from the wrong block.
1806                 // TODO: This should return success instead of failure, see
1807                 // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518
1808                 result.last_failed_block = block_hash;
1809                 result.status = ScanResult::FAILURE;
1810                 break;
1811             }
1812             for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1813                 SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, *block_height, block_hash, (int)posInBlock}, fUpdate);
1814             }
1815             // scan succeeded, record block as most recent successfully scanned
1816             result.last_scanned_block = block_hash;
1817             result.last_scanned_height = *block_height;
1818         } else {
1819             // could not scan block, keep scanning but record this block as the most recent failure
1820             result.last_failed_block = block_hash;
1821             result.status = ScanResult::FAILURE;
1822         }
1823         if (block_hash == stop_block) {
1824             break;
1825         }
1826         {
1827             auto locked_chain = chain().lock();
1828             Optional<int> tip_height = locked_chain->getHeight();
1829             if (!tip_height || *tip_height <= block_height || !locked_chain->getBlockHeight(block_hash)) {
1830                 // break successfully when rescan has reached the tip, or
1831                 // previous block is no longer on the chain due to a reorg
1832                 break;
1833             }
1834 
1835             // increment block and verification progress
1836             block_hash = locked_chain->getBlockHash(++*block_height);
1837             progress_current = chain().guessVerificationProgress(block_hash);
1838 
1839             // handle updated tip hash
1840             const uint256 prev_tip_hash = tip_hash;
1841             tip_hash = locked_chain->getBlockHash(*tip_height);
1842             if (stop_block.IsNull() && prev_tip_hash != tip_hash) {
1843                 // in case the tip has changed, update progress max
1844                 progress_end = chain().guessVerificationProgress(tip_hash);
1845             }
1846         }
1847     }
1848     ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 100); // hide progress dialog in GUI
1849     if (block_height && fAbortRescan) {
1850         WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", *block_height, progress_current);
1851         result.status = ScanResult::USER_ABORT;
1852     } else if (block_height && chain().shutdownRequested()) {
1853         WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", *block_height, progress_current);
1854         result.status = ScanResult::USER_ABORT;
1855     } else {
1856         WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
1857     }
1858     return result;
1859 }
1860 
ReacceptWalletTransactions()1861 void CWallet::ReacceptWalletTransactions()
1862 {
1863     // If transactions aren't being broadcasted, don't let them into local mempool either
1864     if (!fBroadcastTransactions)
1865         return;
1866     std::map<int64_t, CWalletTx*> mapSorted;
1867 
1868     // Sort pending wallet transactions based on their initial wallet insertion order
1869     for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
1870         const uint256& wtxid = item.first;
1871         CWalletTx& wtx = item.second;
1872         assert(wtx.GetHash() == wtxid);
1873 
1874         int nDepth = wtx.GetDepthInMainChain();
1875 
1876         if (!(wtx.IsCoinBase() || wtx.IsCoinStake()) && (nDepth == 0 && !wtx.isAbandoned())) {
1877             mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
1878         }
1879     }
1880 
1881     // Try to add wallet transactions to memory pool
1882     for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
1883         CWalletTx& wtx = *(item.second);
1884         std::string unused_err_string;
1885         wtx.SubmitMemoryPoolAndRelay(unused_err_string, false);
1886     }
1887 }
1888 
SubmitMemoryPoolAndRelay(std::string & err_string,bool relay)1889 bool CWalletTx::SubmitMemoryPoolAndRelay(std::string& err_string, bool relay)
1890 {
1891     // Can't relay if wallet is not broadcasting
1892     if (!pwallet->GetBroadcastTransactions()) return false;
1893     // Don't relay abandoned transactions
1894     if (isAbandoned()) return false;
1895     // Don't try to submit coinbase transactions. These would fail anyway but would
1896     // cause log spam.
1897     if (IsCoinBase() || IsCoinStake()) return false;
1898     // Don't try to submit conflicted or confirmed transactions.
1899     if (GetDepthInMainChain() != 0) return false;
1900 
1901     // Submit transaction to mempool for relay
1902     pwallet->WalletLogPrintf("Submitting wtx %s to mempool for relay\n", GetHash().ToString());
1903     // We must set fInMempool here - while it will be re-set to true by the
1904     // entered-mempool callback, if we did not there would be a race where a
1905     // user could call sendmoney in a loop and hit spurious out of funds errors
1906     // because we think that this newly generated transaction's change is
1907     // unavailable as we're not yet aware that it is in the mempool.
1908     //
1909     // Irrespective of the failure reason, un-marking fInMempool
1910     // out-of-order is incorrect - it should be unmarked when
1911     // TransactionRemovedFromMempool fires.
1912     bool ret = pwallet->chain().broadcastTransaction(tx, pwallet->m_default_max_tx_fee, relay, err_string);
1913     fInMempool |= ret;
1914     return ret;
1915 }
1916 
GetConflicts() const1917 std::set<uint256> CWalletTx::GetConflicts() const
1918 {
1919     std::set<uint256> result;
1920     if (pwallet != nullptr)
1921     {
1922         uint256 myHash = GetHash();
1923         result = pwallet->GetConflicts(myHash);
1924         result.erase(myHash);
1925     }
1926     return result;
1927 }
1928 
GetCachableAmount(AmountType type,const isminefilter & filter,bool recalculate) const1929 CAmount CWalletTx::GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate) const
1930 {
1931     auto& amount = m_amounts[type];
1932     if (recalculate || !amount.m_cached[filter]) {
1933         amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) : pwallet->GetCredit(*tx, filter));
1934         m_is_cache_empty = false;
1935     }
1936     return amount.m_value[filter];
1937 }
1938 
GetDebit(const isminefilter & filter) const1939 CAmount CWalletTx::GetDebit(const isminefilter& filter) const
1940 {
1941     if (tx->vin.empty())
1942         return 0;
1943 
1944     CAmount debit = 0;
1945     if (filter & ISMINE_SPENDABLE) {
1946         debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
1947     }
1948     if (filter & ISMINE_WATCH_ONLY) {
1949         debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
1950     }
1951     return debit;
1952 }
1953 
GetCredit(const isminefilter & filter) const1954 CAmount CWalletTx::GetCredit(const isminefilter& filter) const
1955 {
1956     // Must wait until coinbase is safely deep enough in the chain before valuing it
1957     if (IsImmatureCoinBase())
1958         return 0;
1959 
1960     CAmount credit = 0;
1961     if (filter & ISMINE_SPENDABLE) {
1962         // GetBalance can assume transactions in mapWallet won't change
1963         credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE);
1964     }
1965     if (filter & ISMINE_WATCH_ONLY) {
1966         credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY);
1967     }
1968     return credit;
1969 }
1970 
GetImmatureCredit(bool fUseCache) const1971 CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
1972 {
1973     if (IsImmatureCoinBase() && IsInMainChain()) {
1974         return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
1975     }
1976 
1977     return 0;
1978 }
1979 
GetStakeCredit(bool fUseCache) const1980 CAmount CWalletTx::GetStakeCredit(bool fUseCache) const
1981 {
1982     if (IsImmatureCoinStake() && IsInMainChain()) {
1983         return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
1984     }
1985 
1986     return 0;
1987 }
1988 
GetAvailableCredit(bool fUseCache,const isminefilter & filter) const1989 CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const
1990 {
1991     if (pwallet == nullptr)
1992         return 0;
1993 
1994     // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
1995     bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL;
1996 
1997     // Must wait until coinbase is safely deep enough in the chain before valuing it
1998     if (IsImmature())
1999         return 0;
2000 
2001     if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
2002         return m_amounts[AVAILABLE_CREDIT].m_value[filter];
2003     }
2004 
2005     bool allow_used_addresses = (filter & ISMINE_USED) || !pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
2006     CAmount nCredit = 0;
2007     uint256 hashTx = GetHash();
2008     for (unsigned int i = 0; i < tx->vout.size(); i++)
2009     {
2010         if (!pwallet->IsSpent(hashTx, i) && (allow_used_addresses || !pwallet->IsSpentKey(hashTx, i))) {
2011             const CTxOut &txout = tx->vout[i];
2012             nCredit += pwallet->GetCredit(txout, filter);
2013             if (!MoneyRange(nCredit))
2014                 throw std::runtime_error(std::string(__func__) + " : value out of range");
2015         }
2016     }
2017 
2018     if (allow_cache) {
2019         m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
2020         m_is_cache_empty = false;
2021     }
2022 
2023     return nCredit;
2024 }
2025 
GetImmatureWatchOnlyCredit(const bool fUseCache) const2026 CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
2027 {
2028     if (IsImmatureCoinBase() && IsInMainChain()) {
2029         return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
2030     }
2031 
2032     return 0;
2033 }
2034 
GetStakeWatchOnlyCredit(const bool fUseCache) const2035 CAmount CWalletTx::GetStakeWatchOnlyCredit(const bool fUseCache) const
2036 {
2037     if (IsImmatureCoinStake() && IsInMainChain()) {
2038         return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
2039     }
2040 
2041     return 0;
2042 }
2043 
GetChange() const2044 CAmount CWalletTx::GetChange() const
2045 {
2046     if (fChangeCached)
2047         return nChangeCached;
2048     nChangeCached = pwallet->GetChange(*tx);
2049     fChangeCached = true;
2050     return nChangeCached;
2051 }
2052 
InMempool() const2053 bool CWalletTx::InMempool() const
2054 {
2055     return fInMempool;
2056 }
2057 
IsTrusted(interfaces::Chain::Lock & locked_chain) const2058 bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const
2059 {
2060     std::set<uint256> s;
2061     return IsTrusted(locked_chain, s);
2062 }
2063 
IsTrusted(interfaces::Chain::Lock & locked_chain,std::set<uint256> & trusted_parents) const2064 bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint256>& trusted_parents) const
2065 {
2066     // Quick answer in most cases
2067     if (!locked_chain.checkFinalTx(*tx)) return false;
2068     int nDepth = GetDepthInMainChain();
2069     if (nDepth >= 1) return true;
2070     if (nDepth < 0) return false;
2071     // using wtx's cached debit
2072     if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) return false;
2073 
2074     // Don't trust unconfirmed transactions from us unless they are in the mempool.
2075     if (!InMempool()) return false;
2076 
2077     // Trusted if all inputs are from us and are in the mempool:
2078     for (const CTxIn& txin : tx->vin)
2079     {
2080         // Transactions not sent by us: not trusted
2081         const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
2082         if (parent == nullptr) return false;
2083         const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
2084         // Check that this specific input being spent is trusted
2085         if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false;
2086         // If we've already trusted this parent, continue
2087         if (trusted_parents.count(parent->GetHash())) continue;
2088         // Recurse to check that the parent is also trusted
2089         if (!parent->IsTrusted(locked_chain, trusted_parents)) return false;
2090         trusted_parents.insert(parent->GetHash());
2091     }
2092     return true;
2093 }
2094 
IsEquivalentTo(const CWalletTx & _tx) const2095 bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
2096 {
2097         CMutableTransaction tx1 {*this->tx};
2098         CMutableTransaction tx2 {*_tx.tx};
2099         for (auto& txin : tx1.vin) txin.scriptSig = CScript();
2100         for (auto& txin : tx2.vin) txin.scriptSig = CScript();
2101         return CTransaction(tx1) == CTransaction(tx2);
2102 }
2103 
2104 // Rebroadcast transactions from the wallet. We do this on a random timer
2105 // to slightly obfuscate which transactions come from our wallet.
2106 //
2107 // Ideally, we'd only resend transactions that we think should have been
2108 // mined in the most recent block. Any transaction that wasn't in the top
2109 // blockweight of transactions in the mempool shouldn't have been mined,
2110 // and so is probably just sitting in the mempool waiting to be confirmed.
2111 // Rebroadcasting does nothing to speed up confirmation and only damages
2112 // privacy.
ResendWalletTransactions()2113 void CWallet::ResendWalletTransactions()
2114 {
2115     // During reindex, importing and IBD, old wallet transactions become
2116     // unconfirmed. Don't resend them as that would spam other nodes.
2117     if (!chain().isReadyToBroadcast()) return;
2118 
2119     // Do this infrequently and randomly to avoid giving away
2120     // that these are our transactions.
2121     if (GetTime() < nNextResend || !fBroadcastTransactions) return;
2122     bool fFirst = (nNextResend == 0);
2123     nNextResend = GetTime() + GetRand(30 * 60);
2124     if (fFirst) return;
2125 
2126     // Only do it if there's been a new block since last time
2127     if (m_best_block_time < nLastResend) return;
2128     nLastResend = GetTime();
2129 
2130     int submitted_tx_count = 0;
2131 
2132     { // locked_chain and cs_wallet scope
2133         auto locked_chain = chain().lock();
2134         LOCK(cs_wallet);
2135 
2136         // Relay transactions
2137         for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
2138             CWalletTx& wtx = item.second;
2139             // Attempt to rebroadcast all txes more than 5 minutes older than
2140             // the last block. SubmitMemoryPoolAndRelay() will not rebroadcast
2141             // any confirmed or conflicting txs.
2142             if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
2143             std::string unused_err_string;
2144             if (wtx.SubmitMemoryPoolAndRelay(unused_err_string, true)) ++submitted_tx_count;
2145         }
2146     } // locked_chain and cs_wallet
2147 
2148     if (submitted_tx_count > 0) {
2149         WalletLogPrintf("%s: resubmit %u unconfirmed transactions\n", __func__, submitted_tx_count);
2150     }
2151 }
2152 
2153 /** @} */ // end of mapWallet
2154 
MaybeResendWalletTxs()2155 void MaybeResendWalletTxs()
2156 {
2157     for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
2158         pwallet->ResendWalletTransactions();
2159     }
2160 }
2161 
2162 
2163 /** @defgroup Actions
2164  *
2165  * @{
2166  */
2167 
2168 
GetBalance(const int min_depth,bool avoid_reuse) const2169 CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) const
2170 {
2171     Balance ret;
2172     isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
2173     {
2174         auto locked_chain = chain().lock();
2175         LOCK(cs_wallet);
2176         std::set<uint256> trusted_parents;
2177         for (const auto& entry : mapWallet)
2178         {
2179             const CWalletTx& wtx = entry.second;
2180             const bool is_trusted{wtx.IsTrusted(*locked_chain, trusted_parents)};
2181             const int tx_depth{wtx.GetDepthInMainChain()};
2182             const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
2183             const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
2184             if (is_trusted && tx_depth >= min_depth) {
2185                 ret.m_mine_trusted += tx_credit_mine;
2186                 ret.m_watchonly_trusted += tx_credit_watchonly;
2187             }
2188             if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
2189                 ret.m_mine_untrusted_pending += tx_credit_mine;
2190                 ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
2191             }
2192             ret.m_mine_immature += wtx.GetImmatureCredit();
2193             ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit();
2194             ret.m_mine_stake += wtx.GetStakeCredit();
2195             ret.m_watchonly_stake += wtx.GetStakeWatchOnlyCredit();
2196         }
2197     }
2198     return ret;
2199 }
2200 
GetAvailableBalance(const CCoinControl * coinControl) const2201 CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
2202 {
2203     auto locked_chain = chain().lock();
2204     LOCK(cs_wallet);
2205 
2206     CAmount balance = 0;
2207     std::vector<COutput> vCoins;
2208     AvailableCoins(*locked_chain, vCoins, true, coinControl);
2209     for (const COutput& out : vCoins) {
2210         if (out.fSpendable) {
2211             balance += out.tx->tx->vout[out.i].nValue;
2212         }
2213     }
2214     return balance;
2215 }
2216 
AvailableCoins(interfaces::Chain::Lock & locked_chain,std::vector<COutput> & vCoins,bool fOnlySafe,const CCoinControl * coinControl,const CAmount & nMinimumAmount,const CAmount & nMaximumAmount,const CAmount & nMinimumSumAmount,const uint64_t nMaximumCount) const2217 void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount) const
2218 {
2219     AssertLockHeld(cs_wallet);
2220 
2221     vCoins.clear();
2222     CAmount nTotal = 0;
2223     // Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where
2224     // a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses
2225     bool allow_used_addresses = !IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || (coinControl && !coinControl->m_avoid_address_reuse);
2226     const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH};
2227     const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH};
2228 
2229     std::set<uint256> trusted_parents;
2230     for (const auto& entry : mapWallet)
2231     {
2232         const uint256& wtxid = entry.first;
2233         const CWalletTx& wtx = entry.second;
2234 
2235         if (!locked_chain.checkFinalTx(*wtx.tx)) {
2236             continue;
2237         }
2238 
2239         if (wtx.IsImmature())
2240             continue;
2241 
2242         int nDepth = wtx.GetDepthInMainChain();
2243         if (nDepth < 0)
2244             continue;
2245 
2246         // We should not consider coins which aren't at least in our mempool
2247         // It's possible for these to be conflicted via ancestors which we may never be able to detect
2248         if (nDepth == 0 && !wtx.InMempool())
2249             continue;
2250 
2251         bool safeTx = wtx.IsTrusted(locked_chain, trusted_parents);
2252 
2253         // We should not consider coins from transactions that are replacing
2254         // other transactions.
2255         //
2256         // Example: There is a transaction A which is replaced by bumpfee
2257         // transaction B. In this case, we want to prevent creation of
2258         // a transaction B' which spends an output of B.
2259         //
2260         // Reason: If transaction A were initially confirmed, transactions B
2261         // and B' would no longer be valid, so the user would have to create
2262         // a new transaction C to replace B'. However, in the case of a
2263         // one-block reorg, transactions B' and C might BOTH be accepted,
2264         // when the user only wanted one of them. Specifically, there could
2265         // be a 1-block reorg away from the chain where transactions A and C
2266         // were accepted to another chain where B, B', and C were all
2267         // accepted.
2268         if (nDepth == 0 && wtx.mapValue.count("replaces_txid")) {
2269             safeTx = false;
2270         }
2271 
2272         // Similarly, we should not consider coins from transactions that
2273         // have been replaced. In the example above, we would want to prevent
2274         // creation of a transaction A' spending an output of A, because if
2275         // transaction B were initially confirmed, conflicting with A and
2276         // A', we wouldn't want to the user to create a transaction D
2277         // intending to replace A', but potentially resulting in a scenario
2278         // where A, A', and D could all be accepted (instead of just B and
2279         // D, or just A and A' like the user would want).
2280         if (nDepth == 0 && wtx.mapValue.count("replaced_by_txid")) {
2281             safeTx = false;
2282         }
2283 
2284         if (fOnlySafe && !safeTx) {
2285             continue;
2286         }
2287 
2288         if (nDepth < min_depth || nDepth > max_depth) {
2289             continue;
2290         }
2291 
2292         for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
2293             if (wtx.tx->vout[i].nValue < nMinimumAmount || wtx.tx->vout[i].nValue > nMaximumAmount)
2294                 continue;
2295 
2296             if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i)))
2297                 continue;
2298 
2299             if (IsLockedCoin(entry.first, i))
2300                 continue;
2301 
2302             if (IsSpent(wtxid, i))
2303                 continue;
2304 
2305             isminetype mine = IsMine(wtx.tx->vout[i]);
2306 
2307             if (mine == ISMINE_NO) {
2308                 continue;
2309             }
2310 
2311             if (!allow_used_addresses && IsSpentKey(wtxid, i)) {
2312                 continue;
2313             }
2314 
2315             std::unique_ptr<SigningProvider> provider = GetSolvingProvider(wtx.tx->vout[i].scriptPubKey);
2316 
2317             bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false;
2318             bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
2319 
2320             vCoins.push_back(COutput(&wtx, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
2321 
2322             // Checks the sum amount of all UTXO's.
2323             if (nMinimumSumAmount != MAX_MONEY) {
2324                 nTotal += wtx.tx->vout[i].nValue;
2325 
2326                 if (nTotal >= nMinimumSumAmount) {
2327                     return;
2328                 }
2329             }
2330 
2331             // Checks the maximum number of UTXO's.
2332             if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
2333                 return;
2334             }
2335         }
2336     }
2337 }
2338 
GetScriptCache(const COutPoint & prevout,const CScript & scriptPubKey,std::map<COutPoint,CScriptCache> * _insertScriptCache) const2339 const CScriptCache& CWallet::GetScriptCache(const COutPoint& prevout, const CScript& scriptPubKey, std::map<COutPoint, CScriptCache>* _insertScriptCache) const
2340 {
2341     auto it = prevoutScriptCache.find(prevout);
2342     if(it == prevoutScriptCache.end())
2343     {
2344         std::map<COutPoint, CScriptCache>& insertScriptCache = _insertScriptCache == nullptr ? prevoutScriptCache : *_insertScriptCache;
2345         if((int32_t)insertScriptCache.size() > m_staker_max_utxo_script_cache)
2346         {
2347             insertScriptCache.clear();
2348         }
2349 
2350         // The script check for utxo is expensive operations, so cache the data for further use
2351         CScriptCache scriptCache;
2352         scriptCache.contract = scriptPubKey.HasOpCall() || scriptPubKey.HasOpCreate();
2353         if(!scriptCache.contract)
2354         {
2355             scriptCache.keyId = ExtractPublicKeyHash(scriptPubKey, &(scriptCache.keyIdOk));
2356             if(scriptCache.keyIdOk)
2357             {
2358                 std::unique_ptr<SigningProvider> provider = GetSolvingProvider(scriptPubKey);
2359                 scriptCache.solvable = provider ? IsSolvable(*provider, scriptPubKey) : false;
2360             }
2361         }
2362         insertScriptCache[prevout] = scriptCache;
2363         return insertScriptCache[prevout];
2364     }
2365 
2366     return it->second;
2367 }
2368 
valueUtxoSort(const std::pair<COutPoint,CAmount> & a,const std::pair<COutPoint,CAmount> & b)2369 bool valueUtxoSort(const std::pair<COutPoint,CAmount>& a,
2370                 const std::pair<COutPoint,CAmount>& b) {
2371     return a.second > b.second;
2372 }
2373 
ListCoins(interfaces::Chain::Lock & locked_chain) const2374 std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Chain::Lock& locked_chain) const
2375 {
2376     AssertLockHeld(cs_wallet);
2377 
2378     std::map<CTxDestination, std::vector<COutput>> result;
2379     std::vector<COutput> availableCoins;
2380 
2381     AvailableCoins(locked_chain, availableCoins);
2382 
2383     for (const COutput& coin : availableCoins) {
2384         CTxDestination address;
2385         if ((coin.fSpendable || (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.fSolvable)) &&
2386             ExtractDestination(FindNonChangeParentOutput(*coin.tx->tx, coin.i).scriptPubKey, address)) {
2387             result[address].emplace_back(std::move(coin));
2388         }
2389     }
2390 
2391     std::vector<COutPoint> lockedCoins;
2392     ListLockedCoins(lockedCoins);
2393     // Include watch-only for LegacyScriptPubKeyMan wallets without private keys
2394     const bool include_watch_only = GetLegacyScriptPubKeyMan() && IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
2395     const isminetype is_mine_filter = include_watch_only ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
2396     for (const COutPoint& output : lockedCoins) {
2397         auto it = mapWallet.find(output.hash);
2398         if (it != mapWallet.end()) {
2399             int depth = it->second.GetDepthInMainChain();
2400             if (depth >= 0 && output.n < it->second.tx->vout.size() &&
2401                 IsMine(it->second.tx->vout[output.n]) == is_mine_filter
2402             ) {
2403                 CTxDestination address;
2404                 if (ExtractDestination(FindNonChangeParentOutput(*it->second.tx, output.n).scriptPubKey, address)) {
2405                     result[address].emplace_back(
2406                         &it->second, output.n, depth, true /* spendable */, true /* solvable */, false /* safe */);
2407                 }
2408             }
2409         }
2410     }
2411 
2412     return result;
2413 }
2414 
FindNonChangeParentOutput(const CTransaction & tx,int output) const2415 const CTxOut& CWallet::FindNonChangeParentOutput(const CTransaction& tx, int output) const
2416 {
2417     const CTransaction* ptx = &tx;
2418     int n = output;
2419     while (IsChange(ptx->vout[n]) && ptx->vin.size() > 0) {
2420         const COutPoint& prevout = ptx->vin[0].prevout;
2421         auto it = mapWallet.find(prevout.hash);
2422         if (it == mapWallet.end() || it->second.tx->vout.size() <= prevout.n ||
2423             !IsMine(it->second.tx->vout[prevout.n])) {
2424             break;
2425         }
2426         ptx = it->second.tx.get();
2427         n = prevout.n;
2428     }
2429     return ptx->vout[n];
2430 }
2431 
SelectCoinsMinConf(const CAmount & nTargetValue,const CoinEligibilityFilter & eligibility_filter,std::vector<OutputGroup> groups,std::set<CInputCoin> & setCoinsRet,CAmount & nValueRet,const CoinSelectionParams & coin_selection_params,bool & bnb_used) const2432 bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups,
2433                                  std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const
2434 {
2435     setCoinsRet.clear();
2436     nValueRet = 0;
2437 
2438     std::vector<OutputGroup> utxo_pool;
2439     if (coin_selection_params.use_bnb) {
2440         // Get long term estimate
2441         FeeCalculation feeCalc;
2442         CCoinControl temp;
2443         temp.m_confirm_target = 1008;
2444         CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, &feeCalc);
2445 
2446         // Calculate cost of change
2447         CAmount cost_of_change = GetDiscardRate(*this).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
2448 
2449         // Filter by the min conf specs and add to utxo_pool and calculate effective value
2450         for (OutputGroup& group : groups) {
2451             if (!group.EligibleForSpending(eligibility_filter)) continue;
2452 
2453             group.fee = 0;
2454             group.long_term_fee = 0;
2455             group.effective_value = 0;
2456             for (auto it = group.m_outputs.begin(); it != group.m_outputs.end(); ) {
2457                 const CInputCoin& coin = *it;
2458                 CAmount effective_value = coin.txout.nValue - (coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes));
2459                 // Only include outputs that are positive effective value (i.e. not dust)
2460                 if (effective_value > 0) {
2461                     group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes);
2462                     group.long_term_fee += coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
2463                     if (coin_selection_params.m_subtract_fee_outputs) {
2464                         group.effective_value += coin.txout.nValue;
2465                     } else {
2466                         group.effective_value += effective_value;
2467                     }
2468                     ++it;
2469                 } else {
2470                     it = group.Discard(coin);
2471                 }
2472             }
2473             if (group.effective_value > 0) utxo_pool.push_back(group);
2474         }
2475         // Calculate the fees for things that aren't inputs
2476         CAmount not_input_fees = coin_selection_params.effective_fee.GetFee(coin_selection_params.tx_noinputs_size);
2477         bnb_used = true;
2478         return SelectCoinsBnB(utxo_pool, nTargetValue, cost_of_change, setCoinsRet, nValueRet, not_input_fees);
2479     } else {
2480         // Filter by the min conf specs and add to utxo_pool
2481         for (const OutputGroup& group : groups) {
2482             if (!group.EligibleForSpending(eligibility_filter)) continue;
2483             utxo_pool.push_back(group);
2484         }
2485         bnb_used = false;
2486         return KnapsackSolver(nTargetValue, utxo_pool, setCoinsRet, nValueRet);
2487     }
2488 }
2489 
SelectCoins(const std::vector<COutput> & vAvailableCoins,const CAmount & nTargetValue,std::set<CInputCoin> & setCoinsRet,CAmount & nValueRet,const CCoinControl & coin_control,CoinSelectionParams & coin_selection_params,bool & bnb_used) const2490 bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const
2491 {
2492     std::vector<COutput> vCoins(vAvailableCoins);
2493     CAmount value_to_select = nTargetValue;
2494 
2495     // Default to bnb was not used. If we use it, we set it later
2496     bnb_used = false;
2497 
2498     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
2499     if (coin_control.HasSelected() && !coin_control.fAllowOtherInputs)
2500     {
2501         for (const COutput& out : vCoins)
2502         {
2503             if (!out.fSpendable)
2504                  continue;
2505             nValueRet += out.tx->tx->vout[out.i].nValue;
2506             setCoinsRet.insert(out.GetInputCoin());
2507         }
2508         return (nValueRet >= nTargetValue);
2509     }
2510 
2511     // calculate value from preset inputs and store them
2512     std::set<CInputCoin> setPresetCoins;
2513     CAmount nValueFromPresetInputs = 0;
2514 
2515     std::vector<COutPoint> vPresetInputs;
2516     coin_control.ListSelected(vPresetInputs);
2517     for (const COutPoint& outpoint : vPresetInputs)
2518     {
2519         std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
2520         if (it != mapWallet.end())
2521         {
2522             const CWalletTx& wtx = it->second;
2523             // Clearly invalid input, fail
2524             if (wtx.tx->vout.size() <= outpoint.n) {
2525                 return false;
2526             }
2527             // Just to calculate the marginal byte size
2528             CInputCoin coin(wtx.tx, outpoint.n, wtx.GetSpendSize(outpoint.n, false));
2529             nValueFromPresetInputs += coin.txout.nValue;
2530             if (coin.m_input_bytes <= 0) {
2531                 return false; // Not solvable, can't estimate size for fee
2532             }
2533             coin.effective_value = coin.txout.nValue - coin_selection_params.effective_fee.GetFee(coin.m_input_bytes);
2534             if (coin_selection_params.use_bnb) {
2535                 value_to_select -= coin.effective_value;
2536             } else {
2537                 value_to_select -= coin.txout.nValue;
2538             }
2539             setPresetCoins.insert(coin);
2540         } else {
2541             return false; // TODO: Allow non-wallet inputs
2542         }
2543     }
2544 
2545     // remove preset inputs from vCoins
2546     for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
2547     {
2548         if (setPresetCoins.count(it->GetInputCoin()))
2549             it = vCoins.erase(it);
2550         else
2551             ++it;
2552     }
2553 
2554     // form groups from remaining coins; note that preset coins will not
2555     // automatically have their associated (same address) coins included
2556     if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
2557         // Cases where we have 11+ outputs all pointing to the same destination may result in
2558         // privacy leaks as they will potentially be deterministically sorted. We solve that by
2559         // explicitly shuffling the outputs before processing
2560         Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
2561     }
2562     std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);
2563 
2564     unsigned int limit_ancestor_count;
2565     unsigned int limit_descendant_count;
2566     chain().getPackageLimits(limit_ancestor_count, limit_descendant_count);
2567     size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count);
2568     size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count);
2569     bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS);
2570 
2571     bool res = value_to_select <= 0 ||
2572         SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 6, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2573         SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(1, 1, 0), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used) ||
2574         (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2575         (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2576         (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2577         (m_spend_zero_conf_change && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used)) ||
2578         (m_spend_zero_conf_change && !fRejectLongChains && SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max()), groups, setCoinsRet, nValueRet, coin_selection_params, bnb_used));
2579 
2580     // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
2581     util::insert(setCoinsRet, setPresetCoins);
2582 
2583     // add preset inputs to the total value selected
2584     nValueRet += nValueFromPresetInputs;
2585 
2586     return res;
2587 }
2588 
SignTransaction(CMutableTransaction & tx) const2589 bool CWallet::SignTransaction(CMutableTransaction& tx) const
2590 {
2591     AssertLockHeld(cs_wallet);
2592 
2593     // Build coins map
2594     std::map<COutPoint, Coin> coins;
2595     for (auto& input : tx.vin) {
2596         std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
2597         if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
2598             return false;
2599         }
2600         const CWalletTx& wtx = mi->second;
2601         coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], wtx.m_confirm.block_height, wtx.IsCoinBase(), wtx.IsCoinStake());
2602     }
2603     std::map<int, std::string> input_errors;
2604     return SignTransaction(tx, coins, SIGHASH_ALL, input_errors);
2605 }
2606 
SignTransaction(CMutableTransaction & tx,const std::map<COutPoint,Coin> & coins,int sighash,std::map<int,std::string> & input_errors) const2607 bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
2608 {
2609     // Sign the tx with ScriptPubKeyMans
2610     // Because each ScriptPubKeyMan can sign more than one input, we need to keep track of each ScriptPubKeyMan that has signed this transaction.
2611     // Each iteration, we may sign more txins than the txin that is specified in that iteration.
2612     // We assume that each input is signed by only one ScriptPubKeyMan.
2613     std::set<uint256> visited_spk_mans;
2614     for (unsigned int i = 0; i < tx.vin.size(); i++) {
2615         // Get the prevout
2616         CTxIn& txin = tx.vin[i];
2617         auto coin = coins.find(txin.prevout);
2618         if (coin == coins.end() || coin->second.IsSpent()) {
2619             input_errors[i] = "Input not found or already spent";
2620             continue;
2621         }
2622 
2623         // Check if this input is complete
2624         SignatureData sigdata = DataFromTransaction(tx, i, coin->second.out);
2625         if (sigdata.complete) {
2626             continue;
2627         }
2628 
2629         // Input needs to be signed, find the right ScriptPubKeyMan
2630         std::set<ScriptPubKeyMan*> spk_mans = GetScriptPubKeyMans(coin->second.out.scriptPubKey, sigdata);
2631         if (spk_mans.size() == 0) {
2632             input_errors[i] = "Unable to sign input, missing keys";
2633             continue;
2634         }
2635 
2636         for (auto& spk_man : spk_mans) {
2637             // If we've already been signed by this spk_man, skip it
2638             if (visited_spk_mans.count(spk_man->GetID()) > 0) {
2639                 continue;
2640             }
2641 
2642             // Sign the tx.
2643             // spk_man->SignTransaction will return true if the transaction is complete,
2644             // so we can exit early and return true if that happens.
2645             if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
2646                 return true;
2647             }
2648 
2649             // Add this spk_man to visited_spk_mans so we can skip it later
2650             visited_spk_mans.insert(spk_man->GetID());
2651         }
2652     }
2653     return false;
2654 }
2655 
FillPSBT(PartiallySignedTransaction & psbtx,bool & complete,int sighash_type,bool sign,bool bip32derivs) const2656 TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs) const
2657 {
2658     LOCK(cs_wallet);
2659     // Get all of the previous transactions
2660     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2661         const CTxIn& txin = psbtx.tx->vin[i];
2662         PSBTInput& input = psbtx.inputs.at(i);
2663 
2664         if (PSBTInputSigned(input)) {
2665             continue;
2666         }
2667 
2668         // If we have no utxo, grab it from the wallet.
2669         if (!input.non_witness_utxo) {
2670             const uint256& txhash = txin.prevout.hash;
2671             const auto it = mapWallet.find(txhash);
2672             if (it != mapWallet.end()) {
2673                 const CWalletTx& wtx = it->second;
2674                 // We only need the non_witness_utxo, which is a superset of the witness_utxo.
2675                 //   The signing code will switch to the smaller witness_utxo if this is ok.
2676                 input.non_witness_utxo = wtx.tx;
2677             }
2678         }
2679     }
2680 
2681     // Fill in information from ScriptPubKeyMans
2682     // Because each ScriptPubKeyMan may be able to fill more than one input, we need to keep track of each ScriptPubKeyMan that has filled this psbt.
2683     // Each iteration, we may fill more inputs than the input that is specified in that iteration.
2684     // We assume that each input is filled by only one ScriptPubKeyMan
2685     std::set<uint256> visited_spk_mans;
2686     for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
2687         const CTxIn& txin = psbtx.tx->vin[i];
2688         PSBTInput& input = psbtx.inputs.at(i);
2689 
2690         if (PSBTInputSigned(input)) {
2691             continue;
2692         }
2693 
2694         // Get the scriptPubKey to know which ScriptPubKeyMan to use
2695         CScript script;
2696         if (!input.witness_utxo.IsNull()) {
2697             script = input.witness_utxo.scriptPubKey;
2698         } else if (input.non_witness_utxo) {
2699             if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
2700                 return TransactionError::MISSING_INPUTS;
2701             }
2702             script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
2703         } else {
2704             // There's no UTXO so we can just skip this now
2705             continue;
2706         }
2707         SignatureData sigdata;
2708         input.FillSignatureData(sigdata);
2709         std::set<ScriptPubKeyMan*> spk_mans = GetScriptPubKeyMans(script, sigdata);
2710         if (spk_mans.size() == 0) {
2711             continue;
2712         }
2713 
2714         for (auto& spk_man : spk_mans) {
2715             // If we've already been signed by this spk_man, skip it
2716             if (visited_spk_mans.count(spk_man->GetID()) > 0) {
2717                 continue;
2718             }
2719 
2720             // Fill in the information from the spk_man
2721             TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
2722             if (res != TransactionError::OK) {
2723                 return res;
2724             }
2725 
2726             // Add this spk_man to visited_spk_mans so we can skip it later
2727             visited_spk_mans.insert(spk_man->GetID());
2728         }
2729     }
2730 
2731     // Complete if every input is now signed
2732     complete = true;
2733     for (const auto& input : psbtx.inputs) {
2734         complete &= PSBTInputSigned(input);
2735     }
2736 
2737     return TransactionError::OK;
2738 }
2739 
SignMessage(const std::string & message,const PKHash & pkhash,std::string & str_sig) const2740 SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
2741 {
2742     SignatureData sigdata;
2743     CScript script_pub_key = GetScriptForDestination(pkhash);
2744     for (const auto& spk_man_pair : m_spk_managers) {
2745         if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
2746             return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
2747         }
2748     }
2749     return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
2750 }
2751 
FundTransaction(CMutableTransaction & tx,CAmount & nFeeRet,int & nChangePosInOut,std::string & strFailReason,bool lockUnspents,const std::set<int> & setSubtractFeeFromOutputs,CCoinControl coinControl)2752 bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
2753 {
2754     std::vector<CRecipient> vecSend;
2755 
2756     // Turn the txout set into a CRecipient vector.
2757     for (size_t idx = 0; idx < tx.vout.size(); idx++) {
2758         const CTxOut& txOut = tx.vout[idx];
2759         CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1};
2760         vecSend.push_back(recipient);
2761     }
2762 
2763     coinControl.fAllowOtherInputs = true;
2764 
2765     for (const CTxIn& txin : tx.vin) {
2766         coinControl.Select(txin.prevout);
2767     }
2768 
2769     // Acquire the locks to prevent races to the new locked unspents between the
2770     // CreateTransaction call and LockCoin calls (when lockUnspents is true).
2771     auto locked_chain = chain().lock();
2772     LOCK(cs_wallet);
2773 
2774     CAmount nGasFee = GetTxGasFee(tx);
2775     CTransactionRef tx_new;
2776     if (!CreateTransaction(*locked_chain, vecSend, tx_new, nFeeRet, nChangePosInOut, strFailReason, coinControl, false, nGasFee)) {
2777         return false;
2778     }
2779 
2780     if (nChangePosInOut != -1) {
2781         tx.vout.insert(tx.vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
2782     }
2783 
2784     // Copy output sizes from new transaction; they may have had the fee
2785     // subtracted from them.
2786     for (unsigned int idx = 0; idx < tx.vout.size(); idx++) {
2787         tx.vout[idx].nValue = tx_new->vout[idx].nValue;
2788     }
2789 
2790     // Add new txins while keeping original txin scriptSig/order.
2791     for (const CTxIn& txin : tx_new->vin) {
2792         if (!coinControl.IsSelected(txin.prevout)) {
2793             tx.vin.push_back(txin);
2794 
2795             if (lockUnspents) {
2796                 LockCoin(txin.prevout);
2797             }
2798         }
2799     }
2800 
2801     return true;
2802 }
2803 
IsCurrentForAntiFeeSniping(interfaces::Chain & chain,interfaces::Chain::Lock & locked_chain)2804 static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
2805 {
2806     if (chain.isInitialBlockDownload()) {
2807         return false;
2808     }
2809     constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds
2810     if (locked_chain.getBlockTime(*locked_chain.getHeight()) < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
2811         return false;
2812     }
2813     return true;
2814 }
2815 
2816 /**
2817  * Return a height-based locktime for new transactions (uses the height of the
2818  * current chain tip unless we are not synced with the current chain
2819  */
GetLocktimeForNewTransaction(interfaces::Chain & chain,interfaces::Chain::Lock & locked_chain)2820 static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
2821 {
2822     uint32_t const height = locked_chain.getHeight().get_value_or(-1);
2823     uint32_t locktime;
2824     // Discourage fee sniping.
2825     //
2826     // For a large miner the value of the transactions in the best block and
2827     // the mempool can exceed the cost of deliberately attempting to mine two
2828     // blocks to orphan the current best block. By setting nLockTime such that
2829     // only the next block can include the transaction, we discourage this
2830     // practice as the height restricted and limited blocksize gives miners
2831     // considering fee sniping fewer options for pulling off this attack.
2832     //
2833     // A simple way to think about this is from the wallet's point of view we
2834     // always want the blockchain to move forward. By setting nLockTime this
2835     // way we're basically making the statement that we only want this
2836     // transaction to appear in the next block; we don't want to potentially
2837     // encourage reorgs by allowing transactions to appear at lower heights
2838     // than the next block in forks of the best chain.
2839     //
2840     // Of course, the subsidy is high enough, and transaction volume low
2841     // enough, that fee sniping isn't a problem yet, but by implementing a fix
2842     // now we ensure code won't be written that makes assumptions about
2843     // nLockTime that preclude a fix later.
2844     if (IsCurrentForAntiFeeSniping(chain, locked_chain)) {
2845         locktime = height;
2846 
2847         // Secondly occasionally randomly pick a nLockTime even further back, so
2848         // that transactions that are delayed after signing for whatever reason,
2849         // e.g. high-latency mix networks and some CoinJoin implementations, have
2850         // better privacy.
2851         if (GetRandInt(10) == 0)
2852             locktime = std::max(0, (int)locktime - GetRandInt(100));
2853     } else {
2854         // If our chain is lagging behind, we can't discourage fee sniping nor help
2855         // the privacy of high-latency transactions. To avoid leaking a potentially
2856         // unique "nLockTime fingerprint", set nLockTime to a constant.
2857         locktime = 0;
2858     }
2859     assert(locktime <= height);
2860     assert(locktime < LOCKTIME_THRESHOLD);
2861     return locktime;
2862 }
2863 
TransactionChangeType(OutputType change_type,const std::vector<CRecipient> & vecSend)2864 OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend)
2865 {
2866     // If -changetype is specified, always use that change type.
2867     if (change_type != OutputType::CHANGE_AUTO) {
2868         return change_type;
2869     }
2870 
2871     // if m_default_address_type is legacy, use legacy address as change (even
2872     // if some of the outputs are P2WPKH or P2WSH).
2873     if (m_default_address_type == OutputType::LEGACY) {
2874         return OutputType::LEGACY;
2875     }
2876 
2877     // if any destination is P2WPKH or P2WSH, use P2WPKH for the change
2878     // output.
2879     for (const auto& recipient : vecSend) {
2880         // Check if any destination contains a witness program:
2881         int witnessversion = 0;
2882         std::vector<unsigned char> witnessprogram;
2883         if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
2884             return OutputType::BECH32;
2885         }
2886     }
2887 
2888     // else use m_default_address_type for change
2889     return m_default_address_type;
2890 }
2891 
CreateTransaction(interfaces::Chain::Lock & locked_chain,const std::vector<CRecipient> & vecSend,CTransactionRef & tx,CAmount & nFeeRet,int & nChangePosInOut,std::string & strFailReason,const CCoinControl & coin_control,bool sign,CAmount nGasFee,bool hasSender,const CTxDestination & signSenderAddress)2892 bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet,
2893                          int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign, CAmount nGasFee, bool hasSender, const CTxDestination& signSenderAddress)
2894 {
2895     CAmount nValue = 0;
2896     const OutputType change_type = TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend);
2897     ReserveDestination reservedest(this, change_type);
2898     int nChangePosRequest = nChangePosInOut;
2899     unsigned int nSubtractFeeFromAmount = 0;
2900     COutPoint senderInput;
2901     if(hasSender && coin_control.HasSelected()){
2902     	std::vector<COutPoint> vSenderInputs;
2903     	coin_control.ListSelected(vSenderInputs);
2904     	senderInput=vSenderInputs[0];
2905     }
2906     for (const auto& recipient : vecSend)
2907     {
2908         if (nValue < 0 || recipient.nAmount < 0)
2909         {
2910             strFailReason = _("Transaction amounts must not be negative").translated;
2911             return false;
2912         }
2913         nValue += recipient.nAmount;
2914 
2915         if (recipient.fSubtractFeeFromAmount)
2916             nSubtractFeeFromAmount++;
2917     }
2918     if (vecSend.empty())
2919     {
2920         strFailReason = _("Transaction must have at least one recipient").translated;
2921         return false;
2922     }
2923 
2924     CMutableTransaction txNew;
2925 
2926     txNew.nLockTime = GetLocktimeForNewTransaction(chain(), locked_chain);
2927 
2928     FeeCalculation feeCalc;
2929     CAmount nFeeNeeded;
2930     int nBytes;
2931     {
2932         std::set<CInputCoin> setCoins;
2933         std::vector<CInputCoin> vCoins;
2934         auto locked_chain = chain().lock();
2935         LOCK(cs_wallet);
2936         {
2937             std::vector<COutput> vAvailableCoins;
2938             AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0);
2939             CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
2940 
2941             // Create change script that will be used if we need change
2942             // TODO: pass in scriptChange instead of reservedest so
2943             // change transaction isn't always pay-to-bitcoin-address
2944             CScript scriptChange;
2945 
2946             // coin control: send change to custom address
2947             if (!boost::get<CNoDestination>(&coin_control.destChange)) {
2948                 scriptChange = GetScriptForDestination(coin_control.destChange);
2949             } else { // no coin control: send change to newly generated address
2950                 // Note: We use a new key here to keep it from being obvious which side is the change.
2951                 //  The drawback is that by not reusing a previous key, the change may be lost if a
2952                 //  backup is restored, if the backup doesn't have the new private key for the change.
2953                 //  If we reused the old key, it would be possible to add code to look for and
2954                 //  rediscover unknown transactions that were written with keys of ours to recover
2955                 //  post-backup change.
2956 
2957                 // Reserve a new key pair from key pool
2958                 if (!CanGetAddresses(true)) {
2959                     strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.").translated;
2960                     return false;
2961                 }
2962                 CTxDestination dest;
2963                 bool ret = reservedest.GetReservedDestination(dest, true);
2964                 if (!ret)
2965                 {
2966                     strFailReason = "Keypool ran out, please call keypoolrefill first";
2967                     return false;
2968                 }
2969 
2970                 scriptChange = GetScriptForDestination(dest);
2971             }
2972             CTxOut change_prototype_txout(0, scriptChange);
2973             coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
2974 
2975             CFeeRate discard_rate = GetDiscardRate(*this);
2976 
2977             // Get the fee rate to use effective values in coin selection
2978             CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
2979 
2980             nFeeRet = 0;
2981             bool pick_new_inputs = true;
2982             CAmount nValueIn = 0;
2983 
2984             // BnB selector is the only selector used when this is true.
2985             // That should only happen on the first pass through the loop.
2986             coin_selection_params.use_bnb = true;
2987             coin_selection_params.m_subtract_fee_outputs = nSubtractFeeFromAmount != 0; // If we are doing subtract fee from recipient, don't use effective values
2988             // Start with no fee and loop until there is enough fee
2989             while (true)
2990             {
2991                 nChangePosInOut = nChangePosRequest;
2992                 txNew.vin.clear();
2993                 txNew.vout.clear();
2994                 bool fFirst = true;
2995 
2996                 CAmount nValueToSelect = nValue;
2997                 if (nSubtractFeeFromAmount == 0)
2998                     nValueToSelect += nFeeRet;
2999 
3000                 // vouts to the payees
3001                 if (!coin_selection_params.m_subtract_fee_outputs) {
3002                     coin_selection_params.tx_noinputs_size = 11; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
3003                 }
3004                 for (const auto& recipient : vecSend)
3005                 {
3006                     CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
3007 
3008                     if (recipient.fSubtractFeeFromAmount)
3009                     {
3010                         assert(nSubtractFeeFromAmount != 0);
3011                         txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
3012 
3013                         if (fFirst) // first receiver pays the remainder not divisible by output count
3014                         {
3015                             fFirst = false;
3016                             txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
3017                         }
3018                     }
3019                     // Include the fee cost for outputs. Note this is only used for BnB right now
3020                     if (!coin_selection_params.m_subtract_fee_outputs) {
3021                         coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION);
3022                     }
3023 
3024                     if (IsDust(txout, chain().relayDustFee()))
3025                     {
3026                         if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
3027                         {
3028                             if (txout.nValue < 0)
3029                                 strFailReason = _("The transaction amount is too small to pay the fee").translated;
3030                             else
3031                                 strFailReason = _("The transaction amount is too small to send after the fee has been deducted").translated;
3032                         }
3033                         else
3034                             strFailReason = _("Transaction amount too small").translated;
3035                         return false;
3036                     }
3037                     txNew.vout.push_back(txout);
3038                 }
3039 
3040                 // Choose coins to use
3041                 bool bnb_used = false;
3042                 if (pick_new_inputs) {
3043                     nValueIn = 0;
3044                     setCoins.clear();
3045                     int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this);
3046                     // If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
3047                     // as lower-bound to allow BnB to do it's thing
3048                     if (change_spend_size == -1) {
3049                         coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
3050                     } else {
3051                         coin_selection_params.change_spend_size = (size_t)change_spend_size;
3052                     }
3053                     coin_selection_params.effective_fee = nFeeRateNeeded;
3054                     if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used))
3055                     {
3056                         // If BnB was used, it was the first pass. No longer the first pass and continue loop with knapsack.
3057                         if (bnb_used) {
3058                             coin_selection_params.use_bnb = false;
3059                             continue;
3060                         }
3061                         else {
3062                             strFailReason = _("Insufficient funds").translated;
3063                             return false;
3064                         }
3065                     }
3066                 } else {
3067                     bnb_used = false;
3068                 }
3069 
3070                 const CAmount nChange = nValueIn - nValueToSelect;
3071                 if (nChange > 0)
3072                 {
3073                     // send change to existing address
3074                     if (!m_use_change_address &&
3075                             boost::get<CNoDestination>(&coin_control.destChange) &&
3076                             setCoins.size() > 0)
3077                     {
3078                         // setCoins will be added as inputs to the new transaction
3079                         // Set the first input script as change script for the new transaction
3080                         auto pcoin = setCoins.begin();
3081                         scriptChange = pcoin->txout.scriptPubKey;
3082 
3083                         change_prototype_txout = CTxOut(0, scriptChange);
3084                         coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
3085                     }
3086 
3087                     // Fill a vout to ourself
3088                     CTxOut newTxOut(nChange, scriptChange);
3089 
3090                     // Never create dust outputs; if we would, just
3091                     // add the dust to the fee.
3092                     // The nChange when BnB is used is always going to go to fees.
3093                     if (IsDust(newTxOut, discard_rate) || bnb_used)
3094                     {
3095                         nChangePosInOut = -1;
3096                         nFeeRet += nChange;
3097                     }
3098                     else
3099                     {
3100                         if (nChangePosInOut == -1)
3101                         {
3102                             // Insert change txn at random position:
3103                             nChangePosInOut = GetRandInt(txNew.vout.size()+1);
3104                         }
3105                         else if ((unsigned int)nChangePosInOut > txNew.vout.size())
3106                         {
3107                             strFailReason = _("Change index out of range").translated;
3108                             return false;
3109                         }
3110 
3111                         std::vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosInOut;
3112                         txNew.vout.insert(position, newTxOut);
3113                     }
3114                 } else {
3115                     nChangePosInOut = -1;
3116                 }
3117 
3118                 // Move sender input to position 0
3119                 vCoins.clear();
3120                 std::copy(setCoins.begin(), setCoins.end(), std::back_inserter(vCoins));
3121                 if(hasSender && coin_control.HasSelected()){
3122                     for (std::vector<CInputCoin>::size_type i = 0 ; i != vCoins.size(); i++){
3123                         if(vCoins[i].outpoint==senderInput){
3124                             if(i==0)break;
3125                             iter_swap(vCoins.begin(),vCoins.begin()+i);
3126                             break;
3127                         }
3128                     }
3129                 }
3130 
3131                 // Dummy fill vin for maximum size estimation
3132                 //
3133                 for (const auto& coin : vCoins) {
3134                     txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
3135                 }
3136 
3137                 nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
3138                 if (nBytes < 0) {
3139                     strFailReason = _("Signing transaction failed").translated;
3140                     return false;
3141                 }
3142 
3143                 nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, &feeCalc)+nGasFee;
3144                 if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
3145                     // eventually allow a fallback fee
3146                     strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.").translated;
3147                     return false;
3148                 }
3149 
3150                 if (nFeeRet >= nFeeNeeded) {
3151                     // Reduce fee to only the needed amount if possible. This
3152                     // prevents potential overpayment in fees if the coins
3153                     // selected to meet nFeeNeeded result in a transaction that
3154                     // requires less fee than the prior iteration.
3155 
3156                     // If we have no change and a big enough excess fee, then
3157                     // try to construct transaction again only without picking
3158                     // new inputs. We now know we only need the smaller fee
3159                     // (because of reduced tx size) and so we should add a
3160                     // change output. Only try this once.
3161                     if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
3162                         unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size
3163                         CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, nullptr)+nGasFee;
3164                         CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate);
3165                         if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
3166                             pick_new_inputs = false;
3167                             nFeeRet = fee_needed_with_change;
3168                             continue;
3169                         }
3170                     }
3171 
3172                     // If we have change output already, just increase it
3173                     if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3174                         CAmount extraFeePaid = nFeeRet - nFeeNeeded;
3175                         std::vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
3176                         change_position->nValue += extraFeePaid;
3177                         nFeeRet -= extraFeePaid;
3178                     }
3179                     break; // Done, enough fee included.
3180                 }
3181                 else if (!pick_new_inputs) {
3182                     // This shouldn't happen, we should have had enough excess
3183                     // fee to pay for the new output and still meet nFeeNeeded
3184                     // Or we should have just subtracted fee from recipients and
3185                     // nFeeNeeded should not have changed
3186                     strFailReason = _("Transaction fee and change calculation failed").translated;
3187                     return false;
3188                 }
3189 
3190                 // Try to reduce change to include necessary fee
3191                 if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3192                     CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3193                     std::vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
3194                     // Only reduce change if remaining amount is still a large enough output.
3195                     if (change_position->nValue >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
3196                         change_position->nValue -= additionalFeeNeeded;
3197                         nFeeRet += additionalFeeNeeded;
3198                         break; // Done, able to increase fee from change
3199                     }
3200                 }
3201 
3202                 // If subtracting fee from recipients, we now know what fee we
3203                 // need to subtract, we have no reason to reselect inputs
3204                 if (nSubtractFeeFromAmount > 0) {
3205                     pick_new_inputs = false;
3206                 }
3207 
3208                 // Include more fee and try again.
3209                 nFeeRet = nFeeNeeded;
3210                 coin_selection_params.use_bnb = false;
3211                 continue;
3212             }
3213         }
3214 
3215         // Shuffle selected coins and fill in final vin
3216         txNew.vin.clear();
3217         std::vector<CInputCoin> selected_coins(vCoins.begin(), vCoins.end());
3218         int shuffleOffset = 0;
3219         if(hasSender && coin_control.HasSelected() && selected_coins.size() > 0 && selected_coins[0].outpoint==senderInput){
3220             shuffleOffset = 1;
3221         }
3222         Shuffle(selected_coins.begin() + shuffleOffset, selected_coins.end(), FastRandomContext());
3223 
3224         // Note how the sequence number is set to non-maxint so that
3225         // the nLockTime set above actually works.
3226         //
3227         // BIP125 defines opt-in RBF as any nSequence < maxint-1, so
3228         // we use the highest possible value in that range (maxint-2)
3229         // to avoid conflicting with other possible uses of nSequence,
3230         // and in the spirit of "smallest possible change from prior
3231         // behavior."
3232         const uint32_t nSequence = coin_control.m_signal_bip125_rbf.get_value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
3233         for (const auto& coin : selected_coins) {
3234             txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
3235         }
3236 
3237         if (sign)
3238         {
3239             // Signing transaction outputs
3240             int nOut = 0;
3241             for (const auto& output : txNew.vout)
3242             {
3243                 if(output.scriptPubKey.HasOpSender())
3244                 {
3245                     const CScript& scriptPubKey = GetScriptForDestination(signSenderAddress);
3246                     SignatureData sigdata;
3247 
3248                     auto spk_man = GetLegacyScriptPubKeyMan();
3249                     if (!ProduceSignature(*spk_man, MutableTransactionSignatureOutputCreator(&txNew, nOut, output.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
3250                     {
3251                         strFailReason = _("Signing transaction output failed").translated;
3252                         return false;
3253                     }
3254                     else
3255                     {
3256                         if(!UpdateOutput(txNew.vout.at(nOut), sigdata))
3257                         {
3258                             strFailReason = _("Update transaction output failed").translated;
3259                             return false;
3260                         }
3261                     }
3262                 }
3263                 nOut++;
3264             }
3265         }
3266 
3267         if (sign && !SignTransaction(txNew)) {
3268             strFailReason = _("Signing transaction failed").translated;
3269             return false;
3270         }
3271 
3272         // Return the constructed transaction data.
3273         tx = MakeTransactionRef(std::move(txNew));
3274 
3275         // Limit size
3276         if (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)
3277         {
3278             strFailReason = _("Transaction too large").translated;
3279             return false;
3280         }
3281     }
3282 
3283     if (!tx->HasCreateOrCall() && nFeeRet > m_default_max_tx_fee) {
3284         strFailReason = TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED);
3285         return false;
3286     }
3287 
3288     if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
3289         // Lastly, ensure this tx will pass the mempool's chain limits
3290         if (!chain().checkChainLimits(tx)) {
3291             strFailReason = _("Transaction has too long of a mempool chain").translated;
3292             return false;
3293         }
3294     }
3295 
3296     // Before we return success, we assume any change key will be used to prevent
3297     // accidental re-use.
3298     reservedest.KeepDestination();
3299 
3300     WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
3301               nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
3302               feeCalc.est.pass.start, feeCalc.est.pass.end,
3303               100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool),
3304               feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
3305               feeCalc.est.fail.start, feeCalc.est.fail.end,
3306               100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool),
3307               feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
3308     return true;
3309 }
3310 
CommitTransaction(CTransactionRef tx,mapValue_t mapValue,std::vector<std::pair<std::string,std::string>> orderForm)3311 void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
3312 {
3313     auto locked_chain = chain().lock();
3314     LOCK(cs_wallet);
3315 
3316     CWalletTx wtxNew(this, std::move(tx));
3317     wtxNew.mapValue = std::move(mapValue);
3318     wtxNew.vOrderForm = std::move(orderForm);
3319     wtxNew.fTimeReceivedIsTxTime = true;
3320     wtxNew.fFromMe = true;
3321 
3322     WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
3323 
3324     // Add tx to wallet, because if it has change it's also ours,
3325     // otherwise just for transaction history.
3326     AddToWallet(wtxNew);
3327 
3328     // Notify that old coins are spent
3329     for (const CTxIn& txin : wtxNew.tx->vin) {
3330         CWalletTx &coin = mapWallet.at(txin.prevout.hash);
3331         coin.BindWallet(this);
3332         NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
3333     }
3334 
3335     // Get the inserted-CWalletTx from mapWallet so that the
3336     // fInMempool flag is cached properly
3337     CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
3338 
3339     if (!fBroadcastTransactions) {
3340         // Don't submit tx to the mempool
3341         return;
3342     }
3343 
3344     std::string err_string;
3345     if (!wtx.SubmitMemoryPoolAndRelay(err_string, true)) {
3346         WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string);
3347         // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
3348     }
3349 }
3350 
GetStakeWeight(interfaces::Chain::Lock & locked_chain,uint64_t * pStakerWeight,uint64_t * pDelegateWeight) const3351 uint64_t CWallet::GetStakeWeight(interfaces::Chain::Lock& locked_chain, uint64_t* pStakerWeight, uint64_t* pDelegateWeight) const
3352 {
3353     uint64_t nWeight = 0;
3354     uint64_t nStakerWeight = 0;
3355     uint64_t nDelegateWeight = 0;
3356     if(pStakerWeight) *pStakerWeight = nStakerWeight;
3357     if(pDelegateWeight) *pDelegateWeight = nDelegateWeight;
3358 
3359     // Choose coins to use
3360     CAmount nBalance = GetBalance().m_mine_trusted;
3361 
3362     if (nBalance <= m_reserve_balance)
3363         return nWeight;
3364 
3365     std::set<std::pair<const CWalletTx*,unsigned int> > setCoins;
3366     CAmount nValueIn = 0;
3367 
3368     CAmount nTargetValue = nBalance - m_reserve_balance;
3369     if (!SelectCoinsForStaking(locked_chain, nTargetValue, setCoins, nValueIn))
3370         return nWeight;
3371 
3372     if (setCoins.empty())
3373         return nWeight;
3374 
3375     int nHeight = GetLastBlockHeight() + 1;
3376     int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(nHeight);
3377     bool canSuperStake = false;
3378     for(std::pair<const CWalletTx*,unsigned int> pcoin : setCoins)
3379     {
3380         if (pcoin.first->GetDepthInMainChain() >= coinbaseMaturity)
3381         {
3382             // Compute staker weight
3383             CAmount nValue = pcoin.first->tx->vout[pcoin.second].nValue;
3384             nStakerWeight += nValue;
3385 
3386             // Check if the staker can super stake
3387             if(!canSuperStake && nValue >= DEFAULT_STAKING_MIN_UTXO_VALUE)
3388                 canSuperStake = true;
3389         }
3390     }
3391 
3392     if(canSuperStake)
3393     {
3394         // Get the weight of the delegated coins
3395         std::vector<COutPoint> vDelegateCoins;
3396         std::map<uint160, CAmount> mDelegateWeight;
3397         SelectDelegateCoinsForStaking(locked_chain, vDelegateCoins, mDelegateWeight);
3398         for(const COutPoint &prevout : vDelegateCoins)
3399         {
3400             Coin coinPrev;
3401             if(!::ChainstateActive().CoinsTip().GetCoin(prevout, coinPrev)){
3402                 continue;
3403             }
3404 
3405             nDelegateWeight += coinPrev.out.nValue;
3406         }
3407     }
3408 
3409     nWeight = nStakerWeight + nDelegateWeight;
3410     if(pStakerWeight) *pStakerWeight = nStakerWeight;
3411     if(pDelegateWeight) *pDelegateWeight = nDelegateWeight;
3412 
3413     return nWeight;
3414 }
3415 
CreateCoinStakeFromMine(interfaces::Chain::Lock & locked_chain,const FillableSigningProvider & keystore,unsigned int nBits,const CAmount & nTotalFees,uint32_t nTimeBlock,CMutableTransaction & tx,CKey & key,std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins,std::vector<COutPoint> & setSelectedCoins,bool selectedOnly,COutPoint & headerPrevout)3416 bool CWallet::CreateCoinStakeFromMine(interfaces::Chain::Lock& locked_chain, const FillableSigningProvider& keystore, unsigned int nBits, const CAmount& nTotalFees, uint32_t nTimeBlock, CMutableTransaction& tx, CKey& key, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, std::vector<COutPoint>& setSelectedCoins, bool selectedOnly, COutPoint& headerPrevout)
3417 {
3418     CBlockIndex* pindexPrev = ::ChainActive().Tip();
3419     arith_uint256 bnTargetPerCoinDay;
3420     bnTargetPerCoinDay.SetCompact(nBits);
3421 
3422     struct CMutableTransaction txNew(tx);
3423     txNew.vin.clear();
3424     txNew.vout.clear();
3425 
3426     // Mark coin stake transaction
3427     CScript scriptEmpty;
3428     scriptEmpty.clear();
3429     txNew.vout.push_back(CTxOut(0, scriptEmpty));
3430 
3431     // Choose coins to use
3432     CAmount nBalance = GetBalance().m_mine_trusted;
3433 
3434     if (nBalance <= m_reserve_balance)
3435         return false;
3436 
3437     std::vector<std::pair<const CWalletTx*,unsigned int>> vwtxPrev;
3438 
3439     if (setCoins.empty())
3440         return false;
3441 
3442     if(stakeCache.size() > setCoins.size() + 100){
3443         //Determining if the cache is still valid is harder than just clearing it when it gets too big, so instead just clear it
3444         //when it has more than 100 entries more than the actual setCoins.
3445         stakeCache.clear();
3446     }
3447     if(!fHasMinerStakeCache && gArgs.GetBoolArg("-stakecache", DEFAULT_STAKE_CACHE)) {
3448 
3449         for(const std::pair<const CWalletTx*,unsigned int> &pcoin : setCoins)
3450         {
3451             boost::this_thread::interruption_point();
3452             COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
3453             CacheKernel(stakeCache, prevoutStake, pindexPrev, ::ChainstateActive().CoinsTip()); //this will do a 2 disk loads per op
3454         }
3455     }
3456     std::map<COutPoint, CStakeCache>& cache = fHasMinerStakeCache ? minerStakeCache : stakeCache;
3457     int64_t nCredit = 0;
3458     CScript scriptPubKeyKernel;
3459     CScript aggregateScriptPubKeyHashKernel;
3460 
3461     // Populate the list with the selected coins
3462     std::set<std::pair<const CWalletTx*,unsigned int> > setSelected;
3463     if(selectedOnly)
3464     {
3465         for(const COutPoint& prevoutStake : setSelectedCoins)
3466         {
3467             auto it = mapWallet.find(prevoutStake.hash);
3468             if (it != mapWallet.end()) {
3469                 setSelected.insert(std::make_pair(&it->second, prevoutStake.n));
3470             }
3471         }
3472     }
3473 
3474     std::set<std::pair<const CWalletTx*,unsigned int> >& setPrevouts = selectedOnly ? setSelected : setCoins;
3475     for(const std::pair<const CWalletTx*,unsigned int> &pcoin : setPrevouts)
3476     {
3477         bool fKernelFound = false;
3478         boost::this_thread::interruption_point();
3479         // Search backward in time from the given txNew timestamp
3480         // Search nSearchInterval seconds back up to nMaxStakeSearchInterval
3481         COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
3482         if (CheckKernel(pindexPrev, nBits, nTimeBlock, prevoutStake, ::ChainstateActive().CoinsTip(), cache))
3483         {
3484             // Found a kernel
3485             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : kernel found\n");
3486             std::vector<valtype> vSolutions;
3487             CScript scriptPubKeyOut;
3488             scriptPubKeyKernel = pcoin.first->tx->vout[pcoin.second].scriptPubKey;
3489             txnouttype whichType = Solver(scriptPubKeyKernel, vSolutions);
3490             if (whichType == TX_NONSTANDARD)
3491             {
3492                 LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to parse kernel\n");
3493                 break;
3494             }
3495             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : parsed kernel type=%d\n", whichType);
3496             if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
3497             {
3498                 LogPrint(BCLog::COINSTAKE, "CreateCoinStake : no support for kernel type=%d\n", whichType);
3499                 break;  // only support pay to public key and pay to address
3500             }
3501             if (whichType == TX_PUBKEYHASH) // pay to address type
3502             {
3503                 // convert to pay to public key type
3504                 uint160 hash160(vSolutions[0]);
3505                 CKeyID pubKeyHash(hash160);
3506                 if (!keystore.GetKey(pubKeyHash, key))
3507                 {
3508                     LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
3509                     break;  // unable to find corresponding public key
3510                 }
3511                 scriptPubKeyOut << key.GetPubKey().getvch() << OP_CHECKSIG;
3512                 aggregateScriptPubKeyHashKernel = scriptPubKeyKernel;
3513             }
3514             if (whichType == TX_PUBKEY)
3515             {
3516                 valtype& vchPubKey = vSolutions[0];
3517                 CPubKey pubKey(vchPubKey);
3518                 uint160 hash160(Hash160(vchPubKey));
3519                 CKeyID pubKeyHash(hash160);
3520                 if (!keystore.GetKey(pubKeyHash, key))
3521                 {
3522                     LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
3523                     break;  // unable to find corresponding public key
3524                 }
3525 
3526                 if (key.GetPubKey() != pubKey)
3527                 {
3528                     LogPrint(BCLog::COINSTAKE, "CreateCoinStake : invalid key for kernel type=%d\n", whichType);
3529                     break; // keys mismatch
3530                 }
3531 
3532                 scriptPubKeyOut = scriptPubKeyKernel;
3533                 aggregateScriptPubKeyHashKernel = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash160) << OP_EQUALVERIFY << OP_CHECKSIG;
3534             }
3535 
3536             txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
3537             nCredit += pcoin.first->tx->vout[pcoin.second].nValue;
3538             vwtxPrev.push_back(pcoin);
3539             txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
3540 
3541             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : added kernel type=%d\n", whichType);
3542             fKernelFound = true;
3543         }
3544 
3545         if (fKernelFound)
3546         {
3547             headerPrevout = prevoutStake;
3548             break; // if kernel is found stop searching
3549         }
3550     }
3551 
3552     if (nCredit == 0 || nCredit > nBalance - m_reserve_balance)
3553         return false;
3554 
3555     for(const std::pair<const CWalletTx*,unsigned int> &pcoin : setCoins)
3556     {
3557         // Attempt to add more inputs
3558         // Only add coins of the same key/address as kernel
3559         if (txNew.vout.size() == 2 && ((pcoin.first->tx->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->tx->vout[pcoin.second].scriptPubKey == aggregateScriptPubKeyHashKernel))
3560                 && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
3561         {
3562             // Stop adding more inputs if already too many inputs
3563             if (txNew.vin.size() >= GetStakeMaxCombineInputs())
3564                 break;
3565             // Stop adding inputs if reached reserve limit
3566             if (nCredit + pcoin.first->tx->vout[pcoin.second].nValue > nBalance - m_reserve_balance)
3567                 break;
3568             // Do not add additional significant input
3569             if (pcoin.first->tx->vout[pcoin.second].nValue >= GetStakeCombineThreshold())
3570                 continue;
3571 
3572             txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
3573             nCredit += pcoin.first->tx->vout[pcoin.second].nValue;
3574             vwtxPrev.push_back(pcoin);
3575         }
3576     }
3577 
3578     const Consensus::Params& consensusParams = Params().GetConsensus();
3579     int64_t nRewardPiece = 0;
3580     // Calculate reward
3581     {
3582         int64_t nReward = nTotalFees + GetBlockSubsidy(pindexPrev->nHeight + 1, consensusParams);
3583         if (nReward < 0)
3584             return false;
3585 
3586         if(pindexPrev->nHeight < consensusParams.nFirstMPoSBlock || pindexPrev->nHeight >= consensusParams.nLastMPoSBlock)
3587         {
3588             // Keep whole reward
3589             nCredit += nReward;
3590         }
3591         else
3592         {
3593             // Split the reward when mpos is used
3594             nRewardPiece = nReward / consensusParams.nMPoSRewardRecipients;
3595             nCredit += nRewardPiece + nReward % consensusParams.nMPoSRewardRecipients;
3596         }
3597    }
3598 
3599     if (nCredit >= GetStakeSplitThreshold())
3600     {
3601         for(unsigned int i = 0; i < GetStakeSplitOutputs() - 1; i++)
3602             txNew.vout.push_back(CTxOut(0, txNew.vout[1].scriptPubKey)); //split stake
3603     }
3604 
3605     // Set output amount
3606     if (txNew.vout.size() == GetStakeSplitOutputs() + 1)
3607     {
3608         CAmount nValue = (nCredit / GetStakeSplitOutputs() / CENT) * CENT;
3609         for(unsigned int i = 1; i < GetStakeSplitOutputs(); i++)
3610             txNew.vout[i].nValue = nValue;
3611         txNew.vout[GetStakeSplitOutputs()].nValue = nCredit - nValue * (GetStakeSplitOutputs() - 1);
3612     }
3613     else
3614         txNew.vout[1].nValue = nCredit;
3615 
3616     if(pindexPrev->nHeight >= consensusParams.nFirstMPoSBlock && pindexPrev->nHeight < consensusParams.nLastMPoSBlock)
3617     {
3618         if(!CreateMPoSOutputs(txNew, nRewardPiece, pindexPrev->nHeight, consensusParams))
3619             return error("CreateCoinStake : failed to create MPoS reward outputs");
3620     }
3621 
3622     // Append the Refunds To Sender to the transaction outputs
3623     for(unsigned int i = 2; i < tx.vout.size(); i++)
3624     {
3625         txNew.vout.push_back(tx.vout[i]);
3626     }
3627 
3628     // Sign the input coins
3629     int nIn = 0;
3630     for(const std::pair<const CWalletTx*,unsigned int> &pcoin : vwtxPrev)
3631     {
3632         if (!SignSignature(keystore, *pcoin.first->tx, txNew, nIn++, SIGHASH_ALL))
3633             return error("CreateCoinStake : failed to sign coinstake");
3634     }
3635 
3636     // Successfully generated coinstake
3637     tx = txNew;
3638     return true;
3639 }
3640 
CreateCoinStakeFromDelegate(interfaces::Chain::Lock & locked_chain,const FillableSigningProvider & keystore,unsigned int nBits,const CAmount & nTotalFees,uint32_t nTimeBlock,CMutableTransaction & tx,CKey & key,std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins,std::vector<COutPoint> & setDelegateCoins,std::vector<unsigned char> & vchPoD,COutPoint & headerPrevout)3641 bool CWallet::CreateCoinStakeFromDelegate(interfaces::Chain::Lock& locked_chain, const FillableSigningProvider &keystore, unsigned int nBits, const CAmount& nTotalFees, uint32_t nTimeBlock, CMutableTransaction& tx, CKey& key, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, std::vector<COutPoint>& setDelegateCoins, std::vector<unsigned char>& vchPoD, COutPoint& headerPrevout)
3642 {
3643     CBlockIndex* pindexPrev = ::ChainActive().Tip();
3644     arith_uint256 bnTargetPerCoinDay;
3645     bnTargetPerCoinDay.SetCompact(nBits);
3646 
3647     struct CMutableTransaction txNew(tx);
3648     txNew.vin.clear();
3649     txNew.vout.clear();
3650 
3651     // Mark coin stake transaction
3652     CScript scriptEmpty;
3653     scriptEmpty.clear();
3654     txNew.vout.push_back(CTxOut(0, scriptEmpty));
3655 
3656     std::vector<std::pair<const CWalletTx*,unsigned int>> vwtxPrev;
3657     if (setDelegateCoins.empty())
3658         return false;
3659 
3660     if(stakeDelegateCache.size() > setDelegateCoins.size() + 100){
3661         //Determining if the cache is still valid is harder than just clearing it when it gets too big, so instead just clear it
3662         //when it has more than 100 entries more than the actual setCoins.
3663         stakeDelegateCache.clear();
3664     }
3665     if(!fHasMinerStakeCache && gArgs.GetBoolArg("-stakecache", DEFAULT_STAKE_CACHE)) {
3666 
3667         for(const COutPoint &prevoutStake : setDelegateCoins)
3668         {
3669             boost::this_thread::interruption_point();
3670             CacheKernel(stakeDelegateCache, prevoutStake, pindexPrev, ::ChainstateActive().CoinsTip()); //this will do a 2 disk loads per op
3671         }
3672     }
3673     std::map<COutPoint, CStakeCache>& cache = fHasMinerStakeCache ? minerStakeCache : stakeDelegateCache;
3674     int64_t nCredit = 0;
3675     CScript scriptPubKeyKernel;
3676     CScript scriptPubKeyStaker;
3677     Delegation delegation;
3678     bool delegateOutputExist = false;
3679 
3680     for(const COutPoint &prevoutStake : setDelegateCoins)
3681     {
3682         bool fKernelFound = false;
3683         boost::this_thread::interruption_point();
3684         // Search backward in time from the given txNew timestamp
3685         // Search nSearchInterval seconds back up to nMaxStakeSearchInterval
3686         if (CheckKernel(pindexPrev, nBits, nTimeBlock, prevoutStake, ::ChainstateActive().CoinsTip(), cache))
3687         {
3688             // Found a kernel
3689             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : kernel found\n");
3690             std::vector<valtype> vSolutions;
3691 
3692             Coin coinPrev;
3693             if(!::ChainstateActive().CoinsTip().GetCoin(prevoutStake, coinPrev)){
3694                 if(!GetSpentCoinFromMainChain(pindexPrev, prevoutStake, &coinPrev)) {
3695                     return error("CreateCoinStake: Could not find coin and it was not at the tip");
3696                 }
3697             }
3698 
3699             scriptPubKeyKernel = coinPrev.out.scriptPubKey;
3700             txnouttype whichType = Solver(scriptPubKeyKernel, vSolutions);
3701             if (whichType == TX_NONSTANDARD)
3702             {
3703                 LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to parse kernel\n");
3704                 break;
3705             }
3706             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : parsed kernel type=%d\n", whichType);
3707             if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
3708             {
3709                 LogPrint(BCLog::COINSTAKE, "CreateCoinStake : no support for kernel type=%d\n", whichType);
3710                 break;  // only support pay to public key and pay to address
3711             }
3712             if (whichType == TX_PUBKEYHASH) // pay to address type
3713             {
3714                 // convert to pay to public key type
3715                 uint160 hash160(vSolutions[0]);
3716 
3717                 if(!GetDelegationStaker(hash160, delegation))
3718                     return error("CreateCoinStake: Failed to find delegation");
3719 
3720                 if (!keystore.GetKey(CKeyID(delegation.staker), key))
3721                 {
3722                     LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to get staker key for kernel type=%d\n", whichType);
3723                     break;  // unable to find corresponding public key
3724                 }
3725                 scriptPubKeyStaker << key.GetPubKey().getvch() << OP_CHECKSIG;
3726             }
3727             if (whichType == TX_PUBKEY)
3728             {
3729                 valtype& vchPubKey = vSolutions[0];
3730                 uint160 hash160(Hash160(vchPubKey));;
3731 
3732                 if(!GetDelegationStaker(hash160, delegation))
3733                     return error("CreateCoinStake: Failed to find delegation");
3734 
3735                 if (!keystore.GetKey(CKeyID(delegation.staker), key))
3736                 {
3737                     LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to get staker key for kernel type=%d\n", whichType);
3738                     break;  // unable to find corresponding public key
3739                 }
3740 
3741                 scriptPubKeyStaker << key.GetPubKey().getvch() << OP_CHECKSIG;
3742             }
3743 
3744             delegateOutputExist = IsDelegateOutputExist(delegation.fee);
3745             PKHash superStakerAddress(delegation.staker);
3746             COutPoint prevoutSuperStaker;
3747             CAmount nValueSuperStaker = 0;
3748             const CWalletTx* pcoinSuperStaker = GetCoinSuperStaker(setCoins, superStakerAddress, prevoutSuperStaker, nValueSuperStaker);
3749             if(!pcoinSuperStaker)
3750             {
3751                 LogPrint(BCLog::COINSTAKE, "CreateCoinStake : failed to get utxo for super staker %s\n", EncodeDestination(superStakerAddress));
3752                 break;  // unable to find utxo from the super staker
3753             }
3754 
3755             txNew.vin.push_back(CTxIn(prevoutSuperStaker));
3756             nCredit += nValueSuperStaker;
3757             vwtxPrev.push_back(std::make_pair(pcoinSuperStaker, prevoutSuperStaker.n));
3758             txNew.vout.push_back(CTxOut(0, scriptPubKeyStaker));
3759             if(delegateOutputExist)
3760             {
3761                 txNew.vout.push_back(CTxOut(0, scriptPubKeyKernel));
3762             }
3763 
3764             LogPrint(BCLog::COINSTAKE, "CreateCoinStake : added kernel type=%d\n", whichType);
3765             fKernelFound = true;
3766         }
3767 
3768         if (fKernelFound)
3769         {
3770             headerPrevout = prevoutStake;
3771             break; // if kernel is found stop searching
3772         }
3773     }
3774 
3775     if (nCredit == 0)
3776         return false;
3777 
3778     const Consensus::Params& consensusParams = Params().GetConsensus();
3779     int64_t nRewardPiece = 0;
3780     int64_t nRewardOffline = 0;
3781     // Calculate reward
3782     {
3783         int64_t nTotalReward = nTotalFees + GetBlockSubsidy(pindexPrev->nHeight + 1, consensusParams);
3784         if (nTotalReward < 0)
3785             return false;
3786 
3787         if(pindexPrev->nHeight < consensusParams.nFirstMPoSBlock || pindexPrev->nHeight >= consensusParams.nLastMPoSBlock)
3788         {
3789             // Keep whole reward
3790             int64_t nRewardStaker = 0;
3791             if(!SplitOfflineStakeReward(nTotalReward, delegation.fee, nRewardOffline, nRewardStaker))
3792                 return error("CreateCoinStake: Failed to split reward");
3793             nCredit += nRewardStaker;
3794         }
3795         else
3796         {
3797             // Split the reward when mpos is used
3798             nRewardPiece = nTotalReward / consensusParams.nMPoSRewardRecipients;
3799             int64_t nRewardStaker = 0;
3800             int64_t nReward = nRewardPiece + nTotalReward % consensusParams.nMPoSRewardRecipients;
3801             if(!SplitOfflineStakeReward(nReward, delegation.fee, nRewardOffline, nRewardStaker))
3802                 return error("CreateCoinStake: Failed to split reward");
3803             nCredit += nRewardStaker;
3804         }
3805     }
3806 
3807     // Set output amount
3808     txNew.vout[1].nValue = nCredit;
3809     if(delegateOutputExist)
3810     {
3811         txNew.vout[2].nValue = nRewardOffline;
3812     }
3813 
3814     if(pindexPrev->nHeight >= consensusParams.nFirstMPoSBlock && pindexPrev->nHeight < consensusParams.nLastMPoSBlock)
3815     {
3816         if(!CreateMPoSOutputs(txNew, nRewardPiece, pindexPrev->nHeight, consensusParams))
3817             return error("CreateCoinStake : failed to create MPoS reward outputs");
3818     }
3819 
3820     // Append the Refunds To Sender to the transaction outputs
3821     for(unsigned int i = 2; i < tx.vout.size(); i++)
3822     {
3823         txNew.vout.push_back(tx.vout[i]);
3824     }
3825 
3826     // Sign the input coins
3827     int nIn = 0;
3828     for(const std::pair<const CWalletTx*,unsigned int> &pcoin : vwtxPrev)
3829     {
3830         if (!SignSignature(keystore, *pcoin.first->tx, txNew, nIn++, SIGHASH_ALL))
3831             return error("CreateCoinStake : failed to sign coinstake");
3832     }
3833 
3834     // Successfully generated coinstake
3835     tx = txNew;
3836 
3837     // Save Proof Of Delegation
3838     vchPoD = delegation.PoD;
3839 
3840     return true;
3841 }
3842 
GetDelegationStaker(const uint160 & keyid,Delegation & delegation)3843 bool CWallet::GetDelegationStaker(const uint160& keyid, Delegation& delegation)
3844 {
3845     std::map<uint160, Delegation>::iterator it = m_delegations_staker.find(keyid);
3846     if(it == m_delegations_staker.end())
3847         return false;
3848 
3849     delegation = it->second;
3850     return true;
3851 }
3852 
GetCoinSuperStaker(const std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins,const PKHash & superStaker,COutPoint & prevout,CAmount & nValueRet)3853 const CWalletTx* CWallet::GetCoinSuperStaker(const std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, const PKHash& superStaker, COutPoint& prevout, CAmount& nValueRet)
3854 {
3855     for(const std::pair<const CWalletTx*,unsigned int> &pcoin : setCoins)
3856     {
3857         CAmount nValue = pcoin.first->tx->vout[pcoin.second].nValue;
3858         if(nValue < DEFAULT_STAKING_MIN_UTXO_VALUE)
3859             continue;
3860 
3861         CScript scriptPubKey = pcoin.first->tx->vout[pcoin.second].scriptPubKey;
3862         bool OK = false;
3863         PKHash pkhash = ExtractPublicKeyHash(scriptPubKey, &OK);
3864         if(OK && pkhash == superStaker)
3865         {
3866             nValueRet = nValue;
3867             prevout = COutPoint(pcoin.first->GetHash(), pcoin.second);
3868             return pcoin.first;
3869         }
3870     }
3871 
3872     return 0;
3873 }
3874 
CanSuperStake(const std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins,const std::vector<COutPoint> & setDelegateCoins) const3875 bool CWallet::CanSuperStake(const std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, const std::vector<COutPoint>& setDelegateCoins) const
3876 {
3877     bool canSuperStake = false;
3878     if(setDelegateCoins.size() > 0)
3879     {
3880         for(const std::pair<const CWalletTx*,unsigned int> &pcoin : setCoins)
3881         {
3882             CAmount nValue = pcoin.first->tx->vout[pcoin.second].nValue;
3883             if(nValue >= DEFAULT_STAKING_MIN_UTXO_VALUE)
3884             {
3885                 canSuperStake = true;
3886                 break;
3887             }
3888         }
3889     }
3890 
3891     return canSuperStake;
3892 }
3893 
CreateCoinStake(interfaces::Chain::Lock & locked_chain,const FillableSigningProvider & keystore,unsigned int nBits,const CAmount & nTotalFees,uint32_t nTimeBlock,CMutableTransaction & tx,CKey & key,std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins,std::vector<COutPoint> & setSelectedCoins,std::vector<COutPoint> & setDelegateCoins,bool selectedOnly,std::vector<unsigned char> & vchPoD,COutPoint & headerPrevout)3894 bool CWallet::CreateCoinStake(interfaces::Chain::Lock& locked_chain, const FillableSigningProvider& keystore, unsigned int nBits, const CAmount& nTotalFees, uint32_t nTimeBlock, CMutableTransaction& tx, CKey& key, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, std::vector<COutPoint>& setSelectedCoins, std::vector<COutPoint>& setDelegateCoins, bool selectedOnly, std::vector<unsigned char>& vchPoD, COutPoint& headerPrevout)
3895 {
3896     // Can super stake
3897     bool canSuperStake = CanSuperStake(setCoins, setDelegateCoins);
3898 
3899     // Create coinstake from coins that are delegated to me
3900     if(canSuperStake && CreateCoinStakeFromDelegate(locked_chain, keystore, nBits, nTotalFees, nTimeBlock, tx, key, setCoins, setDelegateCoins, vchPoD, headerPrevout))
3901         return true;
3902 
3903     // Create coinstake from coins that are mine
3904     if(setCoins.size() > 0 && CreateCoinStakeFromMine(locked_chain, keystore, nBits, nTotalFees, nTimeBlock, tx, key, setCoins, setSelectedCoins, selectedOnly, headerPrevout))
3905         return true;
3906 
3907     // Fail to create coinstake
3908     return false;
3909 }
3910 
3911 
LoadWallet(bool & fFirstRunRet)3912 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
3913 {
3914     // Even if we don't use this lock in this function, we want to preserve
3915     // lock order in LoadToWallet if query of chain state is needed to know
3916     // tx status. If lock can't be taken (e.g bitcoin-wallet), tx confirmation
3917     // status may be not reliable.
3918     auto locked_chain = LockChain();
3919     LOCK(cs_wallet);
3920 
3921     fFirstRunRet = false;
3922     DBErrors nLoadWalletRet = WalletBatch(*database,"cr+").LoadWallet(this);
3923     if (nLoadWalletRet == DBErrors::NEED_REWRITE)
3924     {
3925         if (database->Rewrite("\x04pool"))
3926         {
3927             for (const auto& spk_man_pair : m_spk_managers) {
3928                 spk_man_pair.second->RewriteDB();
3929             }
3930         }
3931     }
3932 
3933     // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3934     fFirstRunRet = m_spk_managers.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
3935     if (fFirstRunRet) {
3936         assert(m_external_spk_managers.empty());
3937         assert(m_internal_spk_managers.empty());
3938     }
3939 
3940     if (nLoadWalletRet != DBErrors::LOAD_OK)
3941         return nLoadWalletRet;
3942 
3943     return DBErrors::LOAD_OK;
3944 }
3945 
ZapSelectTx(std::vector<uint256> & vHashIn,std::vector<uint256> & vHashOut)3946 DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
3947 {
3948     AssertLockHeld(cs_wallet);
3949     DBErrors nZapSelectTxRet = WalletBatch(*database, "cr+").ZapSelectTx(vHashIn, vHashOut);
3950     for (uint256 hash : vHashOut) {
3951         const auto& it = mapWallet.find(hash);
3952         wtxOrdered.erase(it->second.m_it_wtxOrdered);
3953         mapWallet.erase(it);
3954         NotifyTransactionChanged(this, hash, CT_DELETED);
3955     }
3956 
3957     if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
3958     {
3959         if (database->Rewrite("\x04pool"))
3960         {
3961             for (const auto& spk_man_pair : m_spk_managers) {
3962                 spk_man_pair.second->RewriteDB();
3963             }
3964         }
3965     }
3966 
3967     if (nZapSelectTxRet != DBErrors::LOAD_OK)
3968         return nZapSelectTxRet;
3969 
3970     MarkDirty();
3971 
3972     return DBErrors::LOAD_OK;
3973 }
3974 
ZapWalletTx(std::vector<CWalletTx> & vWtx)3975 DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
3976 {
3977     DBErrors nZapWalletTxRet = WalletBatch(*database,"cr+").ZapWalletTx(vWtx);
3978     if (nZapWalletTxRet == DBErrors::NEED_REWRITE)
3979     {
3980         if (database->Rewrite("\x04pool"))
3981         {
3982             for (const auto& spk_man_pair : m_spk_managers) {
3983                 spk_man_pair.second->RewriteDB();
3984             }
3985         }
3986     }
3987 
3988     if (nZapWalletTxRet != DBErrors::LOAD_OK)
3989         return nZapWalletTxRet;
3990 
3991     return DBErrors::LOAD_OK;
3992 }
3993 
SetAddressBookWithDB(WalletBatch & batch,const CTxDestination & address,const std::string & strName,const std::string & strPurpose)3994 bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
3995 {
3996     bool fUpdated = false;
3997     {
3998         LOCK(cs_wallet);
3999         std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
4000         fUpdated = (mi != m_address_book.end() && !mi->second.IsChange());
4001         m_address_book[address].SetLabel(strName);
4002         if (!strPurpose.empty()) /* update purpose only if requested */
4003             m_address_book[address].purpose = strPurpose;
4004     }
4005     NotifyAddressBookChanged(this, address, strName, IsMine(address) != ISMINE_NO,
4006                              strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
4007     if (!strPurpose.empty() && !batch.WritePurpose(EncodeDestination(address), strPurpose))
4008         return false;
4009     return batch.WriteName(EncodeDestination(address), strName);
4010 }
4011 
SetAddressBook(const CTxDestination & address,const std::string & strName,const std::string & strPurpose)4012 bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
4013 {
4014     WalletBatch batch(*database);
4015     return SetAddressBookWithDB(batch, address, strName, strPurpose);
4016 }
4017 
DelAddressBook(const CTxDestination & address)4018 bool CWallet::DelAddressBook(const CTxDestination& address)
4019 {
4020     // 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)
4021     // NOTE: This isn't a problem for sending addresses because they never have any DestData yet!
4022     // When adding new DestData, it should be considered here whether to retain or delete it (or move it?).
4023     if (IsMine(address)) {
4024         WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please report this bug! %s\n", __func__, PACKAGE_BUGREPORT);
4025         return false;
4026     }
4027 
4028     {
4029         LOCK(cs_wallet);
4030 
4031         // Delete destdata tuples associated with address
4032         std::string strAddress = EncodeDestination(address);
4033         for (const std::pair<const std::string, std::string> &item : m_address_book[address].destdata)
4034         {
4035             WalletBatch(*database).EraseDestData(strAddress, item.first);
4036         }
4037         m_address_book.erase(address);
4038     }
4039 
4040     NotifyAddressBookChanged(this, address, "", IsMine(address) != ISMINE_NO, "", CT_DELETED);
4041 
4042     WalletBatch(*database).ErasePurpose(EncodeDestination(address));
4043     return WalletBatch(*database).EraseName(EncodeDestination(address));
4044 }
4045 
KeypoolCountExternalKeys() const4046 size_t CWallet::KeypoolCountExternalKeys() const
4047 {
4048     AssertLockHeld(cs_wallet);
4049 
4050     unsigned int count = 0;
4051     for (auto spk_man : GetActiveScriptPubKeyMans()) {
4052         count += spk_man->KeypoolCountExternalKeys();
4053     }
4054 
4055     return count;
4056 }
4057 
GetKeyPoolSize() const4058 unsigned int CWallet::GetKeyPoolSize() const
4059 {
4060     AssertLockHeld(cs_wallet);
4061 
4062     unsigned int count = 0;
4063     for (auto spk_man : GetActiveScriptPubKeyMans()) {
4064         count += spk_man->GetKeyPoolSize();
4065     }
4066     return count;
4067 }
4068 
TopUpKeyPool(unsigned int kpSize)4069 bool CWallet::TopUpKeyPool(unsigned int kpSize)
4070 {
4071     LOCK(cs_wallet);
4072     bool res = true;
4073     for (auto spk_man : GetActiveScriptPubKeyMans()) {
4074         res &= spk_man->TopUp(kpSize);
4075     }
4076     return res;
4077 }
4078 
GetNewDestination(const OutputType type,const std::string label,CTxDestination & dest,std::string & error)4079 bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error)
4080 {
4081     LOCK(cs_wallet);
4082     error.clear();
4083     bool result = false;
4084     auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
4085     if (spk_man) {
4086         spk_man->TopUp();
4087         result = spk_man->GetNewDestination(type, dest, error);
4088     }
4089     if (result) {
4090         SetAddressBook(dest, label, "receive");
4091     }
4092 
4093     return result;
4094 }
4095 
GetNewChangeDestination(const OutputType type,CTxDestination & dest,std::string & error)4096 bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error)
4097 {
4098     LOCK(cs_wallet);
4099     error.clear();
4100 
4101     ReserveDestination reservedest(this, type);
4102     if (!reservedest.GetReservedDestination(dest, true)) {
4103         error = "Error: Keypool ran out, please call keypoolrefill first";
4104         return false;
4105     }
4106 
4107     reservedest.KeepDestination();
4108     return true;
4109 }
4110 
GetOldestKeyPoolTime() const4111 int64_t CWallet::GetOldestKeyPoolTime() const
4112 {
4113     LOCK(cs_wallet);
4114     int64_t oldestKey = std::numeric_limits<int64_t>::max();
4115     for (const auto& spk_man_pair : m_spk_managers) {
4116         oldestKey = std::min(oldestKey, spk_man_pair.second->GetOldestKeyPoolTime());
4117     }
4118     return oldestKey;
4119 }
4120 
MarkDestinationsDirty(const std::set<CTxDestination> & destinations)4121 void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
4122     for (auto& entry : mapWallet) {
4123         CWalletTx& wtx = entry.second;
4124         if (wtx.m_is_cache_empty) continue;
4125         for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
4126             CTxDestination dst;
4127             if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
4128                 wtx.MarkDirty();
4129                 break;
4130             }
4131         }
4132     }
4133 }
4134 
GetAddressBalances(interfaces::Chain::Lock & locked_chain) const4135 std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain) const
4136 {
4137     std::map<CTxDestination, CAmount> balances;
4138 
4139     {
4140         LOCK(cs_wallet);
4141         std::set<uint256> trusted_parents;
4142         for (const auto& walletEntry : mapWallet)
4143         {
4144             const CWalletTx& wtx = walletEntry.second;
4145 
4146             if (!wtx.IsTrusted(locked_chain, trusted_parents))
4147                 continue;
4148 
4149             if (wtx.IsImmature())
4150                 continue;
4151 
4152             int nDepth = wtx.GetDepthInMainChain();
4153             if (nDepth < (wtx.IsFromMe(ISMINE_ALL) ? 0 : 1))
4154                 continue;
4155 
4156             for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
4157             {
4158                 CTxDestination addr;
4159                 if (!IsMine(wtx.tx->vout[i]))
4160                     continue;
4161                 if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
4162                     continue;
4163 
4164                 CAmount n = IsSpent(walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
4165 
4166                 if (!balances.count(addr))
4167                     balances[addr] = 0;
4168                 balances[addr] += n;
4169             }
4170         }
4171     }
4172 
4173     return balances;
4174 }
4175 
GetAddressGroupings() const4176 std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings() const
4177 {
4178     AssertLockHeld(cs_wallet);
4179     std::set< std::set<CTxDestination> > groupings;
4180     std::set<CTxDestination> grouping;
4181 
4182     for (const auto& walletEntry : mapWallet)
4183     {
4184         const CWalletTx& wtx = walletEntry.second;
4185 
4186         if (wtx.tx->vin.size() > 0)
4187         {
4188             bool any_mine = false;
4189             // group all input addresses with each other
4190             for (const CTxIn& txin : wtx.tx->vin)
4191             {
4192                 CTxDestination address;
4193                 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
4194                     continue;
4195                 if(!ExtractDestination(mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
4196                     continue;
4197                 grouping.insert(address);
4198                 any_mine = true;
4199             }
4200 
4201             // group change with input addresses
4202             if (any_mine)
4203             {
4204                for (const CTxOut& txout : wtx.tx->vout)
4205                    if (IsChange(txout))
4206                    {
4207                        CTxDestination txoutAddr;
4208                        if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
4209                            continue;
4210                        grouping.insert(txoutAddr);
4211                    }
4212             }
4213             if (grouping.size() > 0)
4214             {
4215                 groupings.insert(grouping);
4216                 grouping.clear();
4217             }
4218         }
4219 
4220         // group lone addrs by themselves
4221         for (const auto& txout : wtx.tx->vout)
4222             if (IsMine(txout))
4223             {
4224                 CTxDestination address;
4225                 if(!ExtractDestination(txout.scriptPubKey, address))
4226                     continue;
4227                 grouping.insert(address);
4228                 groupings.insert(grouping);
4229                 grouping.clear();
4230             }
4231     }
4232 
4233     std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
4234     std::map< CTxDestination, std::set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
4235     for (std::set<CTxDestination> _grouping : groupings)
4236     {
4237         // make a set of all the groups hit by this new group
4238         std::set< std::set<CTxDestination>* > hits;
4239         std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
4240         for (const CTxDestination& address : _grouping)
4241             if ((it = setmap.find(address)) != setmap.end())
4242                 hits.insert((*it).second);
4243 
4244         // merge all hit groups into a new single group and delete old groups
4245         std::set<CTxDestination>* merged = new std::set<CTxDestination>(_grouping);
4246         for (std::set<CTxDestination>* hit : hits)
4247         {
4248             merged->insert(hit->begin(), hit->end());
4249             uniqueGroupings.erase(hit);
4250             delete hit;
4251         }
4252         uniqueGroupings.insert(merged);
4253 
4254         // update setmap
4255         for (const CTxDestination& element : *merged)
4256             setmap[element] = merged;
4257     }
4258 
4259     std::set< std::set<CTxDestination> > ret;
4260     for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
4261     {
4262         ret.insert(*uniqueGrouping);
4263         delete uniqueGrouping;
4264     }
4265 
4266     return ret;
4267 }
4268 
GetLabelAddresses(const std::string & label) const4269 std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
4270 {
4271     LOCK(cs_wallet);
4272     std::set<CTxDestination> result;
4273     for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
4274     {
4275         if (item.second.IsChange()) continue;
4276         const CTxDestination& address = item.first;
4277         const std::string& strName = item.second.GetLabel();
4278         if (strName == label)
4279             result.insert(address);
4280     }
4281     return result;
4282 }
4283 
4284 // disable transaction (only for coinstake)
DisableTransaction(const CTransaction & tx)4285 void CWallet::DisableTransaction(const CTransaction &tx)
4286 {
4287     if (!tx.IsCoinStake() || !IsFromMe(tx))
4288         return; // only disconnecting coinstake requires marking input unspent
4289 
4290     uint256 hash = tx.GetHash();
4291     if(AbandonTransaction(hash))
4292     {
4293         LOCK(cs_wallet);
4294         RemoveFromSpends(hash);
4295         for(const CTxIn& txin : tx.vin)
4296         {
4297             auto it = mapWallet.find(txin.prevout.hash);
4298             if (it != mapWallet.end()) {
4299                 CWalletTx &coin = it->second;
4300                 coin.BindWallet(this);
4301                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
4302             }
4303         }
4304         CWalletTx& wtx = mapWallet.at(hash);
4305         wtx.BindWallet(this);
4306         NotifyTransactionChanged(this, hash, CT_DELETED);
4307     }
4308 }
4309 
GetReservedDestination(CTxDestination & dest,bool internal)4310 bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal)
4311 {
4312     m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
4313     if (!m_spk_man) {
4314         return false;
4315     }
4316 
4317 
4318     if (nIndex == -1)
4319     {
4320         m_spk_man->TopUp();
4321 
4322         CKeyPool keypool;
4323         if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool)) {
4324             return false;
4325         }
4326         fInternal = keypool.fInternal;
4327     }
4328     dest = address;
4329     return true;
4330 }
4331 
KeepDestination()4332 void ReserveDestination::KeepDestination()
4333 {
4334     if (nIndex != -1) {
4335         m_spk_man->KeepDestination(nIndex, type);
4336     }
4337     nIndex = -1;
4338     address = CNoDestination();
4339 }
4340 
ReturnDestination()4341 void ReserveDestination::ReturnDestination()
4342 {
4343     if (nIndex != -1) {
4344         m_spk_man->ReturnDestination(nIndex, fInternal, address);
4345     }
4346     nIndex = -1;
4347     address = CNoDestination();
4348 }
4349 
LockCoin(const COutPoint & output)4350 void CWallet::LockCoin(const COutPoint& output)
4351 {
4352     AssertLockHeld(cs_wallet);
4353     setLockedCoins.insert(output);
4354 }
4355 
UnlockCoin(const COutPoint & output)4356 void CWallet::UnlockCoin(const COutPoint& output)
4357 {
4358     AssertLockHeld(cs_wallet);
4359     setLockedCoins.erase(output);
4360 }
4361 
UnlockAllCoins()4362 void CWallet::UnlockAllCoins()
4363 {
4364     AssertLockHeld(cs_wallet);
4365     setLockedCoins.clear();
4366 }
4367 
IsLockedCoin(uint256 hash,unsigned int n) const4368 bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
4369 {
4370 #ifndef DEBUG_LOCKORDER
4371     AssertLockHeld(cs_wallet);
4372 #endif
4373     COutPoint outpt(hash, n);
4374 
4375     return (setLockedCoins.count(outpt) > 0);
4376 }
4377 
ListLockedCoins(std::vector<COutPoint> & vOutpts) const4378 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
4379 {
4380     AssertLockHeld(cs_wallet);
4381     for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
4382          it != setLockedCoins.end(); it++) {
4383         COutPoint outpt = (*it);
4384         vOutpts.push_back(outpt);
4385     }
4386 }
4387 
4388 /** @} */ // end of Actions
4389 
GetKeyBirthTimes(interfaces::Chain::Lock & locked_chain,std::map<CKeyID,int64_t> & mapKeyBirth) const4390 void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t>& mapKeyBirth) const {
4391     AssertLockHeld(cs_wallet);
4392     mapKeyBirth.clear();
4393 
4394     LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
4395     assert(spk_man != nullptr);
4396     LOCK(spk_man->cs_KeyStore);
4397 
4398     // get birth times for keys with metadata
4399     for (const auto& entry : spk_man->mapKeyMetadata) {
4400         if (entry.second.nCreateTime) {
4401             mapKeyBirth[entry.first] = entry.second.nCreateTime;
4402         }
4403     }
4404 
4405     // map in which we'll infer heights of other keys
4406     const Optional<int> tip_height = locked_chain.getHeight();
4407     const int max_height = tip_height && *tip_height > 144 ? *tip_height - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
4408     std::map<CKeyID, int> mapKeyFirstBlock;
4409     for (const CKeyID &keyid : spk_man->GetKeys()) {
4410         if (mapKeyBirth.count(keyid) == 0)
4411             mapKeyFirstBlock[keyid] = max_height;
4412     }
4413 
4414     // if there are no such keys, we're done
4415     if (mapKeyFirstBlock.empty())
4416         return;
4417 
4418     // find first block that affects those keys, if there are any left
4419     for (const auto& entry : mapWallet) {
4420         // iterate over all wallet transactions...
4421         const CWalletTx &wtx = entry.second;
4422         if (Optional<int> height = locked_chain.getBlockHeight(wtx.m_confirm.hashBlock)) {
4423             // ... which are already in a block
4424             for (const CTxOut &txout : wtx.tx->vout) {
4425                 // iterate over all their outputs
4426                 for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
4427                     // ... and all their affected keys
4428                     std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid);
4429                     if (rit != mapKeyFirstBlock.end() && *height < rit->second)
4430                         rit->second = *height;
4431                 }
4432             }
4433         }
4434     }
4435 
4436     // Extract block timestamps for those keys
4437     for (const auto& entry : mapKeyFirstBlock)
4438         mapKeyBirth[entry.first] = locked_chain.getBlockTime(entry.second) - TIMESTAMP_WINDOW; // block times can be 2h off
4439 }
4440 
4441 /**
4442  * Compute smart timestamp for a transaction being added to the wallet.
4443  *
4444  * Logic:
4445  * - If sending a transaction, assign its timestamp to the current time.
4446  * - If receiving a transaction outside a block, assign its timestamp to the
4447  *   current time.
4448  * - If receiving a block with a future timestamp, assign all its (not already
4449  *   known) transactions' timestamps to the current time.
4450  * - If receiving a block with a past timestamp, before the most recent known
4451  *   transaction (that we care about), assign all its (not already known)
4452  *   transactions' timestamps to the same timestamp as that most-recent-known
4453  *   transaction.
4454  * - If receiving a block with a past timestamp, but after the most recent known
4455  *   transaction, assign all its (not already known) transactions' timestamps to
4456  *   the block time.
4457  *
4458  * For more information see CWalletTx::nTimeSmart,
4459  * https://bitcointalk.org/?topic=54527, or
4460  * https://github.com/bitcoin/bitcoin/pull/1393.
4461  */
ComputeTimeSmart(const CWalletTx & wtx) const4462 unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
4463 {
4464     unsigned int nTimeSmart = wtx.nTimeReceived;
4465     if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
4466         int64_t blocktime;
4467         if (chain().findBlock(wtx.m_confirm.hashBlock, nullptr /* block */, &blocktime)) {
4468             int64_t latestNow = wtx.nTimeReceived;
4469             int64_t latestEntry = 0;
4470 
4471             // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
4472             int64_t latestTolerated = latestNow + 300;
4473             const TxItems& txOrdered = wtxOrdered;
4474             for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
4475                 CWalletTx* const pwtx = it->second;
4476                 if (pwtx == &wtx) {
4477                     continue;
4478                 }
4479                 int64_t nSmartTime;
4480                 nSmartTime = pwtx->nTimeSmart;
4481                 if (!nSmartTime) {
4482                     nSmartTime = pwtx->nTimeReceived;
4483                 }
4484                 if (nSmartTime <= latestTolerated) {
4485                     latestEntry = nSmartTime;
4486                     if (nSmartTime > latestNow) {
4487                         latestNow = nSmartTime;
4488                     }
4489                     break;
4490                 }
4491             }
4492 
4493             nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
4494         } else {
4495             WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
4496         }
4497     }
4498     return nTimeSmart;
4499 }
4500 
AddDestData(WalletBatch & batch,const CTxDestination & dest,const std::string & key,const std::string & value)4501 bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key, const std::string &value)
4502 {
4503     if (boost::get<CNoDestination>(&dest))
4504         return false;
4505 
4506     m_address_book[dest].destdata.insert(std::make_pair(key, value));
4507     return batch.WriteDestData(EncodeDestination(dest), key, value);
4508 }
4509 
EraseDestData(WalletBatch & batch,const CTxDestination & dest,const std::string & key)4510 bool CWallet::EraseDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key)
4511 {
4512     if (!m_address_book[dest].destdata.erase(key))
4513         return false;
4514     return batch.EraseDestData(EncodeDestination(dest), key);
4515 }
4516 
LoadDestData(const CTxDestination & dest,const std::string & key,const std::string & value)4517 void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
4518 {
4519     m_address_book[dest].destdata.insert(std::make_pair(key, value));
4520 }
4521 
GetDestData(const CTxDestination & dest,const std::string & key,std::string * value) const4522 bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
4523 {
4524     std::map<CTxDestination, CAddressBookData>::const_iterator i = m_address_book.find(dest);
4525     if(i != m_address_book.end())
4526     {
4527         CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
4528         if(j != i->second.destdata.end())
4529         {
4530             if(value)
4531                 *value = j->second;
4532             return true;
4533         }
4534     }
4535     return false;
4536 }
4537 
GetDestValues(const std::string & prefix) const4538 std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
4539 {
4540     std::vector<std::string> values;
4541     for (const auto& address : m_address_book) {
4542         for (const auto& data : address.second.destdata) {
4543             if (!data.first.compare(0, prefix.size(), prefix)) {
4544                 values.emplace_back(data.second);
4545             }
4546         }
4547     }
4548     return values;
4549 }
4550 
Verify(interfaces::Chain & chain,const WalletLocation & location,bool salvage_wallet,std::string & error_string,std::vector<std::string> & warnings)4551 bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings)
4552 {
4553     // Do some checking on wallet path. It should be either a:
4554     //
4555     // 1. Path where a directory can be created.
4556     // 2. Path to an existing directory.
4557     // 3. Path to a symlink to a directory.
4558     // 4. For backwards compatibility, the name of a data file in -walletdir.
4559     LOCK(cs_wallets);
4560     const fs::path& wallet_path = location.GetPath();
4561     fs::file_type path_type = fs::symlink_status(wallet_path).type();
4562     if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
4563           (path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
4564           (path_type == fs::regular_file && fs::path(location.GetName()).filename() == location.GetName()))) {
4565         error_string = strprintf(
4566               "Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
4567               "database/log.?????????? files can be stored, a location where such a directory could be created, "
4568               "or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
4569               location.GetName(), GetWalletDir());
4570         return false;
4571     }
4572 
4573     // Make sure that the wallet path doesn't clash with an existing wallet path
4574     if (IsWalletLoaded(wallet_path)) {
4575         error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", location.GetName());
4576         return false;
4577     }
4578 
4579     // Keep same database environment instance across Verify/Recover calls below.
4580     std::unique_ptr<WalletDatabase> database = WalletDatabase::Create(wallet_path);
4581 
4582     try {
4583         if (!WalletBatch::VerifyEnvironment(wallet_path, error_string)) {
4584             return false;
4585         }
4586     } catch (const fs::filesystem_error& e) {
4587         error_string = strprintf("Error loading wallet %s. %s", location.GetName(), fsbridge::get_filesystem_error_message(e));
4588         return false;
4589     }
4590 
4591     if (salvage_wallet) {
4592         // Recover readable keypairs:
4593         CWallet dummyWallet(&chain, WalletLocation(), WalletDatabase::CreateDummy());
4594         std::string backup_filename;
4595         // Even if we don't use this lock in this function, we want to preserve
4596         // lock order in LoadToWallet if query of chain state is needed to know
4597         // tx status. If lock can't be taken, tx confirmation status may be not
4598         // reliable.
4599         auto locked_chain = dummyWallet.LockChain();
4600         if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
4601             return false;
4602         }
4603     }
4604 
4605     return WalletBatch::VerifyDatabaseFile(wallet_path, warnings, error_string);
4606 }
4607 
CreateWalletFromFile(interfaces::Chain & chain,const WalletLocation & location,std::string & error,std::vector<std::string> & warnings,uint64_t wallet_creation_flags)4608 std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags)
4609 {
4610     const std::string walletFile = WalletDataFilePath(location.GetPath()).string();
4611 
4612     // needed to restore wallet transaction meta data after -zapwallettxes
4613     std::vector<CWalletTx> vWtx;
4614 
4615     if (gArgs.GetBoolArg("-zapwallettxes", false)) {
4616         chain.initMessage(_("Zapping all transactions from wallet...").translated);
4617 
4618         std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath()));
4619         DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
4620         if (nZapWalletRet != DBErrors::LOAD_OK) {
4621             error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile);
4622             return nullptr;
4623         }
4624     }
4625 
4626     chain.initMessage(_("Loading wallet...").translated);
4627 
4628     int64_t nStart = GetTimeMillis();
4629     bool fFirstRun = true;
4630     // TODO: Can't use std::make_shared because we need a custom deleter but
4631     // should be possible to use std::allocate_shared.
4632     std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
4633     DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
4634     if (nLoadWalletRet != DBErrors::LOAD_OK) {
4635         if (nLoadWalletRet == DBErrors::CORRUPT) {
4636             error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile);
4637             return nullptr;
4638         }
4639         else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
4640         {
4641             warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
4642                                           " or address book entries might be missing or incorrect.").translated,
4643                 walletFile));
4644         }
4645         else if (nLoadWalletRet == DBErrors::TOO_NEW) {
4646             error = strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME);
4647             return nullptr;
4648         }
4649         else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
4650         {
4651             error = strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME);
4652             return nullptr;
4653         }
4654         else {
4655             error = strprintf(_("Error loading %s").translated, walletFile);
4656             return nullptr;
4657         }
4658     }
4659 
4660     int prev_version = walletInstance->GetVersion();
4661     if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
4662     {
4663         int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
4664         if (nMaxVersion == 0) // the -upgradewallet without argument case
4665         {
4666             walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
4667             nMaxVersion = FEATURE_LATEST;
4668             walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
4669         }
4670         else
4671             walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
4672         if (nMaxVersion < walletInstance->GetVersion())
4673         {
4674             error = _("Cannot downgrade wallet").translated;
4675             return nullptr;
4676         }
4677         walletInstance->SetMaxVersion(nMaxVersion);
4678     }
4679 
4680     // Upgrade to HD if explicit upgrade
4681     if (gArgs.GetBoolArg("-upgradewallet", false)) {
4682         LOCK(walletInstance->cs_wallet);
4683 
4684         // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
4685         int max_version = walletInstance->GetVersion();
4686         if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
4687             error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated;
4688             return nullptr;
4689         }
4690 
4691         for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
4692             if (!spk_man->Upgrade(prev_version, error)) {
4693                 return nullptr;
4694             }
4695         }
4696     }
4697 
4698     if (fFirstRun)
4699     {
4700         // ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
4701         walletInstance->SetMinVersion(FEATURE_LATEST);
4702 
4703         walletInstance->SetWalletFlags(wallet_creation_flags, false);
4704 
4705         // Always create LegacyScriptPubKeyMan for now
4706         walletInstance->SetupLegacyScriptPubKeyMan();
4707 
4708         if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
4709             LOCK(walletInstance->cs_wallet);
4710             for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
4711                 if (!spk_man->SetupGeneration()) {
4712                     error = _("Unable to generate initial keys").translated;
4713                     return nullptr;
4714                 }
4715             }
4716         }
4717 
4718         auto locked_chain = chain.lock();
4719         walletInstance->chainStateFlushed(locked_chain->getTipLocator());
4720     } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
4721         // Make it impossible to disable private keys after creation
4722         error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile);
4723         return NULL;
4724     } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
4725         for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
4726             if (spk_man->HavePrivateKeys()) {
4727                 warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile));
4728                 break;
4729             }
4730         }
4731     }
4732 
4733     if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
4734         error = strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", ""));
4735         return nullptr;
4736     }
4737 
4738     if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) {
4739         error = strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", ""));
4740         return nullptr;
4741     }
4742 
4743     if (gArgs.IsArgSet("-mintxfee")) {
4744         CAmount n = 0;
4745         if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
4746             error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated;
4747             return nullptr;
4748         }
4749         if (n > HIGH_TX_FEE_PER_KB) {
4750             warnings.push_back(AmountHighWarn("-mintxfee").translated + " " +
4751                               _("This is the minimum transaction fee you pay on every transaction.").translated);
4752         }
4753         walletInstance->m_min_fee = CFeeRate(n);
4754     }
4755 
4756     if (gArgs.IsArgSet("-fallbackfee")) {
4757         CAmount nFeePerK = 0;
4758         if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
4759             error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", ""));
4760             return nullptr;
4761         }
4762         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
4763             warnings.push_back(AmountHighWarn("-fallbackfee").translated + " " +
4764                               _("This is the transaction fee you may pay when fee estimates are not available.").translated);
4765         }
4766         walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
4767     }
4768     // Disable fallback fee in case value was set to 0, enable if non-null value
4769     walletInstance->m_allow_fallback_fee = walletInstance->m_fallback_fee.GetFeePerK() != 0;
4770 
4771     if (gArgs.IsArgSet("-discardfee")) {
4772         CAmount nFeePerK = 0;
4773         if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
4774             error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", ""));
4775             return nullptr;
4776         }
4777         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
4778             warnings.push_back(AmountHighWarn("-discardfee").translated + " " +
4779                               _("This is the transaction fee you may discard if change is smaller than dust at this level").translated);
4780         }
4781         walletInstance->m_discard_rate = CFeeRate(nFeePerK);
4782     }
4783     if (gArgs.IsArgSet("-paytxfee")) {
4784         CAmount nFeePerK = 0;
4785         if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
4786             error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated;
4787             return nullptr;
4788         }
4789         if (nFeePerK > HIGH_TX_FEE_PER_KB) {
4790             warnings.push_back(AmountHighWarn("-paytxfee").translated + " " +
4791                               _("This is the transaction fee you will pay if you send a transaction.").translated);
4792         }
4793         walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
4794         if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) {
4795             error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated,
4796                 gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString());
4797             return nullptr;
4798         }
4799     }
4800 
4801     if (gArgs.IsArgSet("-maxtxfee")) {
4802         CAmount nMaxFee = 0;
4803         if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
4804             error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated;
4805             return nullptr;
4806         }
4807         if (nMaxFee > HIGH_MAX_TX_FEE) {
4808             warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated);
4809         }
4810         if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) {
4811             error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated,
4812                                        gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString());
4813             return nullptr;
4814         }
4815         walletInstance->m_default_max_tx_fee = nMaxFee;
4816     }
4817 
4818     if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) {
4819         warnings.push_back(AmountHighWarn("-minrelaytxfee").translated + " " +
4820                     _("The wallet will avoid paying less than the minimum relay fee.").translated);
4821     }
4822 
4823     walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
4824     walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
4825     walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
4826     if(!ParseMoney(gArgs.GetArg("-reservebalance", FormatMoney(DEFAULT_RESERVE_BALANCE)), walletInstance->m_reserve_balance))
4827         walletInstance->m_reserve_balance = DEFAULT_RESERVE_BALANCE;
4828     walletInstance->m_use_change_address = gArgs.GetBoolArg("-usechangeaddress", DEFAULT_USE_CHANGE_ADDRESS);
4829     if(!ParseMoney(gArgs.GetArg("-stakingminutxovalue", FormatMoney(DEFAULT_STAKING_MIN_UTXO_VALUE)), walletInstance->m_staking_min_utxo_value))
4830         walletInstance->m_staking_min_utxo_value = DEFAULT_STAKING_MIN_UTXO_VALUE;
4831     if(!ParseMoney(gArgs.GetArg("-minstakerutxosize", FormatMoney(DEFAULT_STAKER_MIN_UTXO_SIZE)), walletInstance->m_staker_min_utxo_size))
4832         walletInstance->m_staker_min_utxo_size = DEFAULT_STAKER_MIN_UTXO_SIZE;
4833     if (gArgs.IsArgSet("-stakingminfee"))
4834     {
4835         int nStakingMinFee = gArgs.GetArg("-stakingminfee", DEFAULT_STAKING_MIN_FEE);
4836         if(nStakingMinFee < 0 || nStakingMinFee > 100)
4837         {
4838             chain.initError(strprintf(_("Invalid percentage value for -stakingminfee=<n>: '%d' (must be between 0 and 100)").translated, nStakingMinFee));
4839             return nullptr;
4840         }
4841         walletInstance->m_staking_min_fee = nStakingMinFee;
4842     }
4843     walletInstance->m_staker_max_utxo_script_cache = gArgs.GetArg("-maxstakerutxoscriptcache", DEFAULT_STAKER_MAX_UTXO_SCRIPT_CACHE);
4844     walletInstance->m_num_threads = gArgs.GetArg("-stakerthreads", GetNumCores());
4845     walletInstance->m_num_threads = std::max(1, walletInstance->m_num_threads);
4846 
4847     walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
4848 
4849     // Try to top up keypool. No-op if the wallet is locked.
4850     walletInstance->TopUpKeyPool();
4851 
4852     auto locked_chain = chain.lock();
4853     LOCK(walletInstance->cs_wallet);
4854 
4855     int rescan_height = 0;
4856     if (!gArgs.GetBoolArg("-rescan", false))
4857     {
4858         WalletBatch batch(*walletInstance->database);
4859         CBlockLocator locator;
4860         if (batch.ReadBestBlock(locator)) {
4861             if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) {
4862                 rescan_height = *fork_height;
4863             }
4864         }
4865     }
4866 
4867     const Optional<int> tip_height = locked_chain->getHeight();
4868     if (tip_height) {
4869         walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
4870         walletInstance->m_last_block_processed_height = *tip_height;
4871     } else {
4872         walletInstance->m_last_block_processed.SetNull();
4873         walletInstance->m_last_block_processed_height = -1;
4874     }
4875 
4876     if (tip_height && *tip_height != rescan_height)
4877     {
4878         // We can't rescan beyond non-pruned blocks, stop and throw an error.
4879         // This might happen if a user uses an old wallet within a pruned node
4880         // or if they ran -disablewallet for a longer time, then decided to re-enable
4881         if (chain.havePruned()) {
4882             // Exit early and print an error.
4883             // If a block is pruned after this check, we will load the wallet,
4884             // but fail the rescan with a generic error.
4885             int block_height = *tip_height;
4886             while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
4887                 --block_height;
4888             }
4889 
4890             if (rescan_height != block_height) {
4891                 error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated;
4892                 return nullptr;
4893             }
4894         }
4895 
4896         chain.initMessage(_("Rescanning...").translated);
4897         walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
4898 
4899         // No need to read and scan block if block was created before
4900         // our wallet birthday (as adjusted for block time variability)
4901         // The way the 'time_first_key' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
4902         Optional<int64_t> time_first_key = MakeOptional(false, int64_t());;
4903         for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
4904             int64_t time = spk_man->GetTimeFirstKey();
4905             if (!time_first_key || time < *time_first_key) time_first_key = time;
4906         }
4907         if (time_first_key) {
4908             if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
4909                 rescan_height = *first_block;
4910             }
4911         }
4912 
4913         {
4914             WalletRescanReserver reserver(walletInstance.get());
4915             if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
4916                 error = _("Failed to rescan the wallet during initialization").translated;
4917                 return nullptr;
4918             }
4919         }
4920         walletInstance->chainStateFlushed(locked_chain->getTipLocator());
4921         walletInstance->database->IncrementUpdateCounter();
4922 
4923         // Restore wallet transaction metadata after -zapwallettxes=1
4924         if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2")
4925         {
4926             WalletBatch batch(*walletInstance->database);
4927 
4928             for (const CWalletTx& wtxOld : vWtx)
4929             {
4930                 uint256 hash = wtxOld.GetHash();
4931                 std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
4932                 if (mi != walletInstance->mapWallet.end())
4933                 {
4934                     const CWalletTx* copyFrom = &wtxOld;
4935                     CWalletTx* copyTo = &mi->second;
4936                     copyTo->mapValue = copyFrom->mapValue;
4937                     copyTo->vOrderForm = copyFrom->vOrderForm;
4938                     copyTo->nTimeReceived = copyFrom->nTimeReceived;
4939                     copyTo->nTimeSmart = copyFrom->nTimeSmart;
4940                     copyTo->fFromMe = copyFrom->fFromMe;
4941                     copyTo->nOrderPos = copyFrom->nOrderPos;
4942                     batch.WriteTx(*copyTo);
4943                 }
4944             }
4945         }
4946     }
4947 
4948     {
4949         LOCK(cs_wallets);
4950         for (auto& load_wallet : g_load_wallet_fns) {
4951             load_wallet(interfaces::MakeWallet(walletInstance));
4952         }
4953     }
4954 
4955     // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
4956     walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
4957 
4958     walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
4959 
4960     {
4961         walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n",      walletInstance->GetKeyPoolSize());
4962         walletInstance->WalletLogPrintf("mapWallet.size() = %u\n",       walletInstance->mapWallet.size());
4963         walletInstance->WalletLogPrintf("m_address_book.size() = %u\n",  walletInstance->m_address_book.size());
4964     }
4965 
4966     if(!fReindex)
4967         // Clean not reverted coinstake transactions
4968         walletInstance->CleanCoinStake();
4969 
4970     return walletInstance;
4971 }
4972 
FindAddressBookEntry(const CTxDestination & dest,bool allow_change) const4973 const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
4974 {
4975     const auto& address_book_it = m_address_book.find(dest);
4976     if (address_book_it == m_address_book.end()) return nullptr;
4977     if ((!allow_change) && address_book_it->second.IsChange()) {
4978         return nullptr;
4979     }
4980     return &address_book_it->second;
4981 }
4982 
postInitProcess()4983 void CWallet::postInitProcess()
4984 {
4985     auto locked_chain = chain().lock();
4986     LOCK(cs_wallet);
4987 
4988     // Add wallet transactions that aren't already in a block to mempool
4989     // Do this here as mempool requires genesis block to be loaded
4990     ReacceptWalletTransactions();
4991 
4992     // Update wallet transactions with current mempool transactions.
4993     chain().requestMempoolTransactions(*this);
4994 
4995     // Start mine proof-of-stake blocks in the background
4996     if (gArgs.GetBoolArg("-staking", DEFAULT_STAKE)) {
4997         StartStake();
4998     }
4999 }
5000 
BackupWallet(const std::string & strDest) const5001 bool CWallet::BackupWallet(const std::string& strDest) const
5002 {
5003     return database->Backup(strDest);
5004 }
5005 
LoadToken(const CTokenInfo & token)5006 bool CWallet::LoadToken(const CTokenInfo &token)
5007 {
5008     uint256 hash = token.GetHash();
5009     mapToken[hash] = token;
5010 
5011     return true;
5012 }
5013 
LoadTokenTx(const CTokenTx & tokenTx)5014 bool CWallet::LoadTokenTx(const CTokenTx &tokenTx)
5015 {
5016     uint256 hash = tokenTx.GetHash();
5017     mapTokenTx[hash] = tokenTx;
5018 
5019     return true;
5020 }
5021 
AddTokenEntry(const CTokenInfo & token,bool fFlushOnClose)5022 bool CWallet::AddTokenEntry(const CTokenInfo &token, bool fFlushOnClose)
5023 {
5024     LOCK(cs_wallet);
5025 
5026     WalletBatch batch(*database, "r+", fFlushOnClose);
5027 
5028     uint256 hash = token.GetHash();
5029 
5030     bool fInsertedNew = true;
5031 
5032     std::map<uint256, CTokenInfo>::iterator it = mapToken.find(hash);
5033     if(it!=mapToken.end())
5034     {
5035         fInsertedNew = false;
5036     }
5037 
5038     // Write to disk
5039     CTokenInfo wtoken = token;
5040     if(!fInsertedNew)
5041     {
5042         wtoken.nCreateTime = chain().getAdjustedTime();
5043     }
5044     else
5045     {
5046         wtoken.nCreateTime = it->second.nCreateTime;
5047     }
5048 
5049     if (!batch.WriteToken(wtoken))
5050         return false;
5051 
5052     mapToken[hash] = wtoken;
5053 
5054     NotifyTokenChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
5055 
5056     // Refresh token tx
5057     if(fInsertedNew)
5058     {
5059         for(auto it = mapTokenTx.begin(); it != mapTokenTx.end(); it++)
5060         {
5061             uint256 tokenTxHash = it->second.GetHash();
5062             NotifyTokenTransactionChanged(this, tokenTxHash, CT_UPDATED);
5063         }
5064     }
5065 
5066     LogPrintf("AddTokenEntry %s\n", wtoken.GetHash().ToString());
5067 
5068     return true;
5069 }
5070 
AddTokenTxEntry(const CTokenTx & tokenTx,bool fFlushOnClose)5071 bool CWallet::AddTokenTxEntry(const CTokenTx &tokenTx, bool fFlushOnClose)
5072 {
5073     LOCK(cs_wallet);
5074 
5075     WalletBatch batch(*database, "r+", fFlushOnClose);
5076 
5077     uint256 hash = tokenTx.GetHash();
5078 
5079     bool fInsertedNew = true;
5080 
5081     std::map<uint256, CTokenTx>::iterator it = mapTokenTx.find(hash);
5082     if(it!=mapTokenTx.end())
5083     {
5084         fInsertedNew = false;
5085     }
5086 
5087     // Write to disk
5088     CTokenTx wtokenTx = tokenTx;
5089     if(!fInsertedNew)
5090     {
5091         wtokenTx.strLabel = it->second.strLabel;
5092     }
5093     const CBlockIndex *pIndex = ChainActive()[wtokenTx.blockNumber];
5094     wtokenTx.nCreateTime = pIndex ? pIndex->GetBlockTime() : chain().getAdjustedTime();
5095 
5096     if (!batch.WriteTokenTx(wtokenTx))
5097         return false;
5098 
5099     mapTokenTx[hash] = wtokenTx;
5100 
5101     NotifyTokenTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
5102 
5103     LogPrintf("AddTokenTxEntry %s\n", wtokenTx.GetHash().ToString());
5104 
5105     return true;
5106 }
5107 
CKeyPool()5108 CKeyPool::CKeyPool()
5109 {
5110     nTime = GetTime();
5111     fInternal = false;
5112     m_pre_split = false;
5113 }
5114 
CKeyPool(const CPubKey & vchPubKeyIn,bool internalIn)5115 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
5116 {
5117     nTime = GetTime();
5118     vchPubKey = vchPubKeyIn;
5119     fInternal = internalIn;
5120     m_pre_split = false;
5121 }
5122 
GetDepthInMainChain() const5123 int CWalletTx::GetDepthInMainChain() const
5124 {
5125     assert(pwallet != nullptr);
5126 #ifndef DEBUG_LOCKORDER
5127     AssertLockHeld(pwallet->cs_wallet);
5128 #endif
5129     if (isUnconfirmed() || isAbandoned()) return 0;
5130 
5131     return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
5132 }
5133 
GetBlocksToMaturity() const5134 int CWalletTx::GetBlocksToMaturity() const
5135 {
5136     if (!(IsCoinBase() || IsCoinStake()))
5137         return 0;
5138     int chain_depth = GetDepthInMainChain();
5139     int nHeight = pwallet->GetLastBlockHeight() + 1;
5140     int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(nHeight);
5141     return std::max(0, (coinbaseMaturity+1) - chain_depth);
5142 }
5143 
IsImmature() const5144 bool CWalletTx::IsImmature() const
5145 {
5146     // note GetBlocksToMaturity is 0 for non-coinbase tx
5147     return GetBlocksToMaturity() > 0;
5148 }
5149 
IsImmatureCoinBase() const5150 bool CWalletTx::IsImmatureCoinBase() const
5151 {
5152     return IsCoinBase() && IsImmature();
5153 }
5154 
IsImmatureCoinStake() const5155 bool CWalletTx::IsImmatureCoinStake() const
5156 {
5157     return IsCoinStake() && IsImmature();
5158 }
5159 
GroupOutputs(const std::vector<COutput> & outputs,bool single_coin) const5160 std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const {
5161     std::vector<OutputGroup> groups;
5162     std::map<CTxDestination, OutputGroup> gmap;
5163     CTxDestination dst;
5164     for (const auto& output : outputs) {
5165         if (output.fSpendable) {
5166             CInputCoin input_coin = output.GetInputCoin();
5167 
5168             size_t ancestors, descendants;
5169             chain().getTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
5170             if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
5171                 // Limit output groups to no more than 10 entries, to protect
5172                 // against inadvertently creating a too-large transaction
5173                 // when using -avoidpartialspends
5174                 if (gmap[dst].m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
5175                     groups.push_back(gmap[dst]);
5176                     gmap.erase(dst);
5177                 }
5178                 gmap[dst].Insert(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
5179             } else {
5180                 groups.emplace_back(input_coin, output.nDepth, output.tx->IsFromMe(ISMINE_ALL), ancestors, descendants);
5181             }
5182         }
5183     }
5184     if (!single_coin) {
5185         for (const auto& it : gmap) groups.push_back(it.second);
5186     }
5187     return groups;
5188 }
5189 
IsCrypted() const5190 bool CWallet::IsCrypted() const
5191 {
5192     return HasEncryptionKeys();
5193 }
5194 
IsLocked() const5195 bool CWallet::IsLocked() const
5196 {
5197     if (!IsCrypted()) {
5198         return false;
5199     }
5200     LOCK(cs_wallet);
5201     return vMasterKey.empty();
5202 }
5203 
Lock()5204 bool CWallet::Lock()
5205 {
5206     if (!IsCrypted())
5207         return false;
5208 
5209     {
5210         LOCK(cs_wallet);
5211         vMasterKey.clear();
5212     }
5213 
5214     NotifyStatusChanged(this);
5215     return true;
5216 }
5217 
Unlock(const CKeyingMaterial & vMasterKeyIn,bool accept_no_keys)5218 bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
5219 {
5220     {
5221         LOCK(cs_wallet);
5222         for (const auto& spk_man_pair : m_spk_managers) {
5223             if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) {
5224                 return false;
5225             }
5226         }
5227         vMasterKey = vMasterKeyIn;
5228     }
5229     NotifyStatusChanged(this);
5230     return true;
5231 }
5232 
GetActiveScriptPubKeyMans() const5233 std::set<ScriptPubKeyMan*> CWallet::GetActiveScriptPubKeyMans() const
5234 {
5235     std::set<ScriptPubKeyMan*> spk_mans;
5236     for (bool internal : {false, true}) {
5237         for (OutputType t : OUTPUT_TYPES) {
5238             auto spk_man = GetScriptPubKeyMan(t, internal);
5239             if (spk_man) {
5240                 spk_mans.insert(spk_man);
5241             }
5242         }
5243     }
5244     return spk_mans;
5245 }
5246 
GetAllScriptPubKeyMans() const5247 std::set<ScriptPubKeyMan*> CWallet::GetAllScriptPubKeyMans() const
5248 {
5249     std::set<ScriptPubKeyMan*> spk_mans;
5250     for (const auto& spk_man_pair : m_spk_managers) {
5251         spk_mans.insert(spk_man_pair.second.get());
5252     }
5253     return spk_mans;
5254 }
5255 
GetScriptPubKeyMan(const OutputType & type,bool internal) const5256 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const OutputType& type, bool internal) const
5257 {
5258     const std::map<OutputType, ScriptPubKeyMan*>& spk_managers = internal ? m_internal_spk_managers : m_external_spk_managers;
5259     std::map<OutputType, ScriptPubKeyMan*>::const_iterator it = spk_managers.find(type);
5260     if (it == spk_managers.end()) {
5261         WalletLogPrintf("%s scriptPubKey Manager for output type %d does not exist\n", internal ? "Internal" : "External", static_cast<int>(type));
5262         return nullptr;
5263     }
5264     return it->second;
5265 }
5266 
GetScriptPubKeyMans(const CScript & script,SignatureData & sigdata) const5267 std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const
5268 {
5269     std::set<ScriptPubKeyMan*> spk_mans;
5270     for (const auto& spk_man_pair : m_spk_managers) {
5271         if (spk_man_pair.second->CanProvide(script, sigdata)) {
5272             spk_mans.insert(spk_man_pair.second.get());
5273         }
5274     }
5275     return spk_mans;
5276 }
5277 
GetScriptPubKeyMan(const CScript & script) const5278 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const CScript& script) const
5279 {
5280     SignatureData sigdata;
5281     for (const auto& spk_man_pair : m_spk_managers) {
5282         if (spk_man_pair.second->CanProvide(script, sigdata)) {
5283             return spk_man_pair.second.get();
5284         }
5285     }
5286     return nullptr;
5287 }
5288 
GetScriptPubKeyMan(const uint256 & id) const5289 ScriptPubKeyMan* CWallet::GetScriptPubKeyMan(const uint256& id) const
5290 {
5291     if (m_spk_managers.count(id) > 0) {
5292         return m_spk_managers.at(id).get();
5293     }
5294     return nullptr;
5295 }
5296 
GetSolvingProvider(const CScript & script) const5297 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script) const
5298 {
5299     SignatureData sigdata;
5300     return GetSolvingProvider(script, sigdata);
5301 }
5302 
GetSolvingProvider(const CScript & script,SignatureData & sigdata) const5303 std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& script, SignatureData& sigdata) const
5304 {
5305     for (const auto& spk_man_pair : m_spk_managers) {
5306         if (spk_man_pair.second->CanProvide(script, sigdata)) {
5307             return spk_man_pair.second->GetSolvingProvider(script);
5308         }
5309     }
5310     return nullptr;
5311 }
5312 
GetLegacyScriptPubKeyMan() const5313 LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
5314 {
5315     // Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
5316     // Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
5317     auto it = m_internal_spk_managers.find(OutputType::LEGACY);
5318     if (it == m_internal_spk_managers.end()) return nullptr;
5319     return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
5320 }
5321 
GetOrCreateLegacyScriptPubKeyMan()5322 LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
5323 {
5324     SetupLegacyScriptPubKeyMan();
5325     return GetLegacyScriptPubKeyMan();
5326 }
5327 
SetupLegacyScriptPubKeyMan()5328 void CWallet::SetupLegacyScriptPubKeyMan()
5329 {
5330     if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty()) {
5331         return;
5332     }
5333 
5334     auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this));
5335     for (const auto& type : OUTPUT_TYPES) {
5336         m_internal_spk_managers[type] = spk_manager.get();
5337         m_external_spk_managers[type] = spk_manager.get();
5338     }
5339     m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
5340 }
5341 
GetEncryptionKey() const5342 const CKeyingMaterial& CWallet::GetEncryptionKey() const
5343 {
5344     return vMasterKey;
5345 }
5346 
HasEncryptionKeys() const5347 bool CWallet::HasEncryptionKeys() const
5348 {
5349     return !mapMasterKeys.empty();
5350 }
5351 
ConnectScriptPubKeyManNotifiers()5352 void CWallet::ConnectScriptPubKeyManNotifiers()
5353 {
5354     for (const auto& spk_man : GetActiveScriptPubKeyMans()) {
5355         spk_man->NotifyWatchonlyChanged.connect(NotifyWatchonlyChanged);
5356         spk_man->NotifyCanGetAddressesChanged.connect(NotifyCanGetAddressesChanged);
5357     }
5358 }
5359 
GetHash() const5360 uint256 CTokenInfo::GetHash() const
5361 {
5362     return SerializeHash(*this, SER_GETHASH, 0);
5363 }
5364 
GetHash() const5365 uint256 CTokenTx::GetHash() const
5366 {
5367     return SerializeHash(*this, SER_GETHASH, 0);
5368 }
5369 
GetHash() const5370 uint256 CDelegationInfo::GetHash() const
5371 {
5372     return SerializeHash(*this, SER_GETHASH, 0);
5373 }
5374 
GetHash() const5375 uint256 CSuperStakerInfo::GetHash() const
5376 {
5377     return SerializeHash(*this, SER_GETHASH, 0);
5378 }
5379 
GetTokenTxDetails(const CTokenTx & wtx,uint256 & credit,uint256 & debit,std::string & tokenSymbol,uint8_t & decimals) const5380 bool CWallet::GetTokenTxDetails(const CTokenTx &wtx, uint256 &credit, uint256 &debit, std::string &tokenSymbol, uint8_t &decimals) const
5381 {
5382     LOCK(cs_wallet);
5383     bool ret = false;
5384 
5385     for(auto it = mapToken.begin(); it != mapToken.end(); it++)
5386     {
5387         CTokenInfo info = it->second;
5388         if(wtx.strContractAddress == info.strContractAddress)
5389         {
5390             if(wtx.strSenderAddress == info.strSenderAddress)
5391             {
5392                 debit = wtx.nValue;
5393                 tokenSymbol = info.strTokenSymbol;
5394                 decimals = info.nDecimals;
5395                 ret = true;
5396             }
5397 
5398             if(wtx.strReceiverAddress == info.strSenderAddress)
5399             {
5400                 credit = wtx.nValue;
5401                 tokenSymbol = info.strTokenSymbol;
5402                 decimals = info.nDecimals;
5403                 ret = true;
5404             }
5405         }
5406     }
5407 
5408     return ret;
5409 }
5410 
IsTokenTxMine(const CTokenTx & wtx) const5411 bool CWallet::IsTokenTxMine(const CTokenTx &wtx) const
5412 {
5413     LOCK(cs_wallet);
5414     bool ret = false;
5415 
5416     for(auto it = mapToken.begin(); it != mapToken.end(); it++)
5417     {
5418         CTokenInfo info = it->second;
5419         if(wtx.strContractAddress == info.strContractAddress)
5420         {
5421             if(wtx.strSenderAddress == info.strSenderAddress ||
5422                 wtx.strReceiverAddress == info.strSenderAddress)
5423             {
5424                 ret = true;
5425             }
5426         }
5427     }
5428 
5429     return ret;
5430 }
5431 
RemoveTokenEntry(const uint256 & tokenHash,bool fFlushOnClose)5432 bool CWallet::RemoveTokenEntry(const uint256 &tokenHash, bool fFlushOnClose)
5433 {
5434     LOCK(cs_wallet);
5435 
5436     WalletBatch batch(*database, "r+", fFlushOnClose);
5437 
5438     bool fFound = false;
5439 
5440     std::map<uint256, CTokenInfo>::iterator it = mapToken.find(tokenHash);
5441     if(it!=mapToken.end())
5442     {
5443         fFound = true;
5444     }
5445 
5446     if(fFound)
5447     {
5448         // Remove from disk
5449         if (!batch.EraseToken(tokenHash))
5450             return false;
5451 
5452         mapToken.erase(it);
5453 
5454         NotifyTokenChanged(this, tokenHash, CT_DELETED);
5455 
5456         // Refresh token tx
5457         for(auto it = mapTokenTx.begin(); it != mapTokenTx.end(); it++)
5458         {
5459             uint256 tokenTxHash = it->second.GetHash();
5460             NotifyTokenTransactionChanged(this, tokenTxHash, CT_UPDATED);
5461         }
5462     }
5463 
5464     LogPrintf("RemoveTokenEntry %s\n", tokenHash.ToString());
5465 
5466     return true;
5467 }
5468 
CleanTokenTxEntries(bool fFlushOnClose)5469 bool CWallet::CleanTokenTxEntries(bool fFlushOnClose)
5470 {
5471     LOCK(cs_wallet);
5472 
5473     // Open db
5474     WalletBatch batch(*database, "r+", fFlushOnClose);
5475 
5476     // Get all token transaction hashes
5477     std::vector<uint256> tokenTxHashes;
5478     for(auto it = mapTokenTx.begin(); it != mapTokenTx.end(); it++)
5479     {
5480         tokenTxHashes.push_back(it->first);
5481     }
5482 
5483     // Remove existing entries
5484     for(size_t i = 0; i < tokenTxHashes.size(); i++)
5485     {
5486         // Get the I entry
5487         uint256 hashTxI = tokenTxHashes[i];
5488         auto itTxI = mapTokenTx.find(hashTxI);
5489         if(itTxI == mapTokenTx.end()) continue;
5490         CTokenTx tokenTxI = itTxI->second;
5491 
5492         for(size_t j = 0; j < tokenTxHashes.size(); j++)
5493         {
5494             // Skip the same entry
5495             if(i == j) continue;
5496 
5497             // Get the J entry
5498             uint256 hashTxJ = tokenTxHashes[j];
5499             auto itTxJ = mapTokenTx.find(hashTxJ);
5500             if(itTxJ == mapTokenTx.end()) continue;
5501             CTokenTx tokenTxJ = itTxJ->second;
5502 
5503             // Compare I and J entries
5504             if(tokenTxI.strContractAddress != tokenTxJ.strContractAddress) continue;
5505             if(tokenTxI.strSenderAddress != tokenTxJ.strSenderAddress) continue;
5506             if(tokenTxI.strReceiverAddress != tokenTxJ.strReceiverAddress) continue;
5507             if(tokenTxI.blockHash != tokenTxJ.blockHash) continue;
5508             if(tokenTxI.blockNumber != tokenTxJ.blockNumber) continue;
5509             if(tokenTxI.transactionHash != tokenTxJ.transactionHash) continue;
5510 
5511             // Delete the lower entry from disk
5512             size_t nLower = uintTou256(tokenTxI.nValue) < uintTou256(tokenTxJ.nValue) ? i : j;
5513             auto itTx = nLower == i ? itTxI : itTxJ;
5514             uint256 hashTx = nLower == i ? hashTxI : hashTxJ;
5515 
5516             if (!batch.EraseTokenTx(hashTx))
5517                 return false;
5518 
5519             mapTokenTx.erase(itTx);
5520 
5521             NotifyTokenTransactionChanged(this, hashTx, CT_DELETED);
5522 
5523             break;
5524         }
5525     }
5526 
5527     return true;
5528 }
5529 
SetContractBook(const std::string & strAddress,const std::string & strName,const std::string & strAbi)5530 bool CWallet::SetContractBook(const std::string &strAddress, const std::string &strName, const std::string &strAbi)
5531 {
5532     bool fUpdated = false;
5533     {
5534         LOCK(cs_wallet); // mapContractBook
5535         auto mi = mapContractBook.find(strAddress);
5536         fUpdated = mi != mapContractBook.end();
5537         mapContractBook[strAddress].name = strName;
5538         mapContractBook[strAddress].abi = strAbi;
5539     }
5540 
5541     NotifyContractBookChanged(this, strAddress, strName, strAbi, (fUpdated ? CT_UPDATED : CT_NEW) );
5542 
5543     WalletBatch batch(*database, "r+", true);
5544     bool ret = batch.WriteContractData(strAddress, "name", strName);
5545     ret &= batch.WriteContractData(strAddress, "abi", strAbi);
5546     return ret;
5547 }
5548 
DelContractBook(const std::string & strAddress)5549 bool CWallet::DelContractBook(const std::string &strAddress)
5550 {
5551     {
5552         LOCK(cs_wallet); // mapContractBook
5553         mapContractBook.erase(strAddress);
5554     }
5555 
5556     NotifyContractBookChanged(this, strAddress, "", "", CT_DELETED);
5557 
5558     WalletBatch batch(*database, "r+", true);
5559     bool ret = batch.EraseContractData(strAddress, "name");
5560     ret &= batch.EraseContractData(strAddress, "abi");
5561     return ret;
5562 }
5563 
LoadContractData(const std::string & address,const std::string & key,const std::string & value)5564 bool CWallet::LoadContractData(const std::string &address, const std::string &key, const std::string &value)
5565 {
5566     bool ret = true;
5567     if(key == "name")
5568     {
5569         mapContractBook[address].name = value;
5570     }
5571     else if(key == "abi")
5572     {
5573         mapContractBook[address].abi = value;
5574     }
5575     else
5576     {
5577         ret = false;
5578     }
5579     return ret;
5580 }
5581 
LoadDelegation(const CDelegationInfo & delegation)5582 bool CWallet::LoadDelegation(const CDelegationInfo &delegation)
5583 {
5584     uint256 hash = delegation.GetHash();
5585     mapDelegation[hash] = delegation;
5586 
5587     return true;
5588 }
5589 
AddDelegationEntry(const CDelegationInfo & delegation,bool fFlushOnClose)5590 bool CWallet::AddDelegationEntry(const CDelegationInfo& delegation, bool fFlushOnClose)
5591 {
5592     LOCK(cs_wallet);
5593 
5594     WalletBatch batch(*database, "r+", fFlushOnClose);
5595 
5596     uint256 hash = delegation.GetHash();
5597 
5598     bool fInsertedNew = true;
5599 
5600     std::map<uint256, CDelegationInfo>::iterator it = mapDelegation.find(hash);
5601     if(it!=mapDelegation.end())
5602     {
5603         fInsertedNew = false;
5604     }
5605 
5606     // Write to disk
5607     CDelegationInfo wdelegation = delegation;
5608     if(!fInsertedNew)
5609     {
5610         wdelegation.nCreateTime = chain().getAdjustedTime();
5611     }
5612     else
5613     {
5614         wdelegation.nCreateTime = it->second.nCreateTime;
5615     }
5616 
5617     if (!batch.WriteDelegation(wdelegation))
5618         return false;
5619 
5620     mapDelegation[hash] = wdelegation;
5621 
5622     NotifyDelegationChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
5623 
5624     if(fInsertedNew)
5625     {
5626         LogPrintf("AddDelegationEntry %s\n", wdelegation.GetHash().ToString());
5627     }
5628 
5629     return true;
5630 }
5631 
RemoveDelegationEntry(const uint256 & delegationHash,bool fFlushOnClose)5632 bool CWallet::RemoveDelegationEntry(const uint256& delegationHash, bool fFlushOnClose)
5633 {
5634     LOCK(cs_wallet);
5635 
5636     WalletBatch batch(*database, "r+", fFlushOnClose);
5637 
5638     bool fFound = false;
5639 
5640     std::map<uint256, CDelegationInfo>::iterator it = mapDelegation.find(delegationHash);
5641     if(it!=mapDelegation.end())
5642     {
5643         fFound = true;
5644     }
5645 
5646     if(fFound)
5647     {
5648         // Remove from disk
5649         if (!batch.EraseDelegation(delegationHash))
5650             return false;
5651 
5652         mapDelegation.erase(it);
5653 
5654         NotifyDelegationChanged(this, delegationHash, CT_DELETED);
5655     }
5656 
5657     LogPrintf("RemoveDelegationEntry %s\n", delegationHash.ToString());
5658 
5659     return true;
5660 }
5661 
LoadSuperStaker(const CSuperStakerInfo & superStaker)5662 bool CWallet::LoadSuperStaker(const CSuperStakerInfo &superStaker)
5663 {
5664     uint256 hash = superStaker.GetHash();
5665     mapSuperStaker[hash] = superStaker;
5666 
5667     return true;
5668 }
5669 
AddSuperStakerEntry(const CSuperStakerInfo & superStaker,bool fFlushOnClose)5670 bool CWallet::AddSuperStakerEntry(const CSuperStakerInfo& superStaker, bool fFlushOnClose)
5671 {
5672     LOCK(cs_wallet);
5673 
5674     WalletBatch batch(*database, "r+", fFlushOnClose);
5675 
5676     uint256 hash = superStaker.GetHash();
5677 
5678     bool fInsertedNew = true;
5679 
5680     std::map<uint256, CSuperStakerInfo>::iterator it = mapSuperStaker.find(hash);
5681     if(it!=mapSuperStaker.end())
5682     {
5683         fInsertedNew = false;
5684     }
5685 
5686     // Write to disk
5687     CSuperStakerInfo wsuperStaker = superStaker;
5688     if(!fInsertedNew)
5689     {
5690         wsuperStaker.nCreateTime = chain().getAdjustedTime();
5691     }
5692     else
5693     {
5694         wsuperStaker.nCreateTime = it->second.nCreateTime;
5695     }
5696 
5697     if (!batch.WriteSuperStaker(wsuperStaker))
5698         return false;
5699 
5700     mapSuperStaker[hash] = wsuperStaker;
5701 
5702     NotifySuperStakerChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
5703 
5704     if(fInsertedNew)
5705     {
5706         LogPrintf("AddSuperStakerEntry %s\n", wsuperStaker.GetHash().ToString());
5707     }
5708     else
5709     {
5710         fUpdatedSuperStaker = true;
5711     }
5712 
5713     return true;
5714 }
5715 
RemoveSuperStakerEntry(const uint256 & superStakerHash,bool fFlushOnClose)5716 bool CWallet::RemoveSuperStakerEntry(const uint256& superStakerHash, bool fFlushOnClose)
5717 {
5718     LOCK(cs_wallet);
5719 
5720     WalletBatch batch(*database, "r+", fFlushOnClose);
5721 
5722     bool fFound = false;
5723 
5724     std::map<uint256, CSuperStakerInfo>::iterator it = mapSuperStaker.find(superStakerHash);
5725     if(it!=mapSuperStaker.end())
5726     {
5727         fFound = true;
5728     }
5729 
5730     if(fFound)
5731     {
5732         // Remove from disk
5733         if (!batch.EraseSuperStaker(superStakerHash))
5734             return false;
5735 
5736         mapSuperStaker.erase(it);
5737 
5738         NotifySuperStakerChanged(this, superStakerHash, CT_DELETED);
5739     }
5740 
5741     LogPrintf("RemoveSuperStakerEntry %s\n", superStakerHash.ToString());
5742 
5743     return true;
5744 }
5745 
StakeQtums(bool fStake,CConnman * connman)5746 void CWallet::StakeQtums(bool fStake, CConnman* connman)
5747 {
5748     ::StakeQtums(fStake, this, connman, stakeThread);
5749 }
5750 
StartStake(CConnman * connman)5751 void CWallet::StartStake(CConnman *connman)
5752 {
5753     m_enabled_staking = true;
5754     StakeQtums(true, connman);
5755 }
5756 
StopStake()5757 void CWallet::StopStake()
5758 {
5759     if(!stakeThread)
5760     {
5761         if(m_enabled_staking)
5762             m_enabled_staking = false;
5763     }
5764     else
5765     {
5766         m_stop_staking_thread = true;
5767         m_enabled_staking = false;
5768         StakeQtums(false, 0);
5769         stakeThread = 0;
5770         m_stop_staking_thread = false;
5771     }
5772 }
5773 
IsStakeClosing()5774 bool CWallet::IsStakeClosing()
5775 {
5776     return chain().shutdownRequested() || m_stop_staking_thread;
5777 }
5778 
updateDelegationsStaker(const std::map<uint160,Delegation> & delegations_staker)5779 void CWallet::updateDelegationsStaker(const std::map<uint160, Delegation> &delegations_staker)
5780 {
5781     LOCK(cs_wallet);
5782 
5783     // Notify for updated and deleted delegation items
5784     for (std::map<uint160, Delegation>::iterator it=m_delegations_staker.begin(); it!=m_delegations_staker.end();)
5785     {
5786         uint160 addressDelegate = it->first;
5787         std::map<uint160, Delegation>::const_iterator delegation = delegations_staker.find(addressDelegate);
5788         if(delegation == delegations_staker.end())
5789         {
5790             it = m_delegations_staker.erase(it);
5791             m_delegations_weight.erase(addressDelegate);
5792             NotifyDelegationsStakerChanged(this, addressDelegate, CT_DELETED);
5793         }
5794         else
5795         {
5796             if(delegation->second != it->second)
5797             {
5798                 it->second = delegation->second;
5799                 NotifyDelegationsStakerChanged(this, addressDelegate, CT_UPDATED);
5800             }
5801             it++;
5802         }
5803     }
5804 
5805     // Notify for new delegation items
5806     for (std::map<uint160, Delegation>::const_iterator it=delegations_staker.begin(); it!=delegations_staker.end(); it++)
5807     {
5808         if(m_delegations_staker.find(it->first) == m_delegations_staker.end())
5809         {
5810             m_delegations_staker[it->first] = it->second;
5811             NotifyDelegationsStakerChanged(this, it->first, CT_NEW);
5812         }
5813     }
5814 }
5815 
updateDelegationsWeight(const std::map<uint160,CAmount> & delegations_weight)5816 void CWallet::updateDelegationsWeight(const std::map<uint160, CAmount>& delegations_weight)
5817 {
5818     LOCK(cs_wallet);
5819 
5820     for (std::map<uint160, CAmount>::const_iterator mi = delegations_weight.begin(); mi != delegations_weight.end(); mi++)
5821     {
5822         bool updated = true;
5823         uint160 delegate = mi->first;
5824         CAmount weight = mi->second;
5825         std::map<uint160, CAmount>::iterator it = m_delegations_weight.find(delegate);
5826         if(it != m_delegations_weight.end())
5827         {
5828             if(it->second == weight)
5829             {
5830                 updated = false;
5831             }
5832         }
5833 
5834         m_delegations_weight[delegate] = weight;
5835 
5836         if(updated && m_delegations_staker.find(delegate) != m_delegations_staker.end())
5837         {
5838             NotifyDelegationsStakerChanged(this, delegate, CT_UPDATED);
5839         }
5840     }
5841 
5842     for (std::map<uint256, CSuperStakerInfo>::iterator mi = mapSuperStaker.begin(); mi != mapSuperStaker.end(); mi++)
5843     {
5844         uint256 hash = mi->first;
5845         NotifySuperStakerChanged(this, hash, CT_UPDATED);
5846     }
5847 }
5848 
GetSuperStakerWeight(const uint160 & staker) const5849 uint64_t CWallet::GetSuperStakerWeight(const uint160 &staker) const
5850 {
5851     LOCK(cs_wallet);
5852 
5853     uint64_t nWeight = 0;
5854     auto iterator = m_have_coin_superstaker.find(staker);
5855     if (iterator != m_have_coin_superstaker.end() && iterator->second)
5856     {
5857         for (std::map<uint160, Delegation>::const_iterator it=m_delegations_staker.begin(); it!=m_delegations_staker.end(); it++)
5858         {
5859             if(it->second.staker == staker)
5860             {
5861                 uint160 delegate = it->first;
5862                 std::map<uint160, CAmount>::const_iterator mi = m_delegations_weight.find(delegate);
5863                 if(mi != m_delegations_weight.end())
5864                 {
5865                     nWeight += mi->second;
5866                 }
5867             }
5868         }
5869     }
5870 
5871     return nWeight;
5872 }
5873 
GetSuperStaker(CSuperStakerInfo & info,const uint160 & stakerAddress) const5874 bool CWallet::GetSuperStaker(CSuperStakerInfo &info, const uint160 &stakerAddress) const
5875 {
5876     LOCK(cs_wallet);
5877 
5878     for (std::map<uint256, CSuperStakerInfo>::const_iterator it=mapSuperStaker.begin(); it!=mapSuperStaker.end(); it++)
5879     {
5880         if(it->second.stakerAddress == stakerAddress)
5881         {
5882             info = it->second;
5883             return true;
5884         }
5885     }
5886 
5887     return false;
5888 }
5889 
GetStakerAddressBalance(interfaces::Chain::Lock & locked_chain,const PKHash & staker,CAmount & balance,CAmount & stake,CAmount & weight) const5890 void CWallet::GetStakerAddressBalance(interfaces::Chain::Lock &locked_chain, const PKHash &staker, CAmount &balance, CAmount &stake, CAmount& weight) const
5891 {
5892     AssertLockHeld(cs_main);
5893     AssertLockHeld(cs_wallet);
5894 
5895     balance = 0;
5896     stake = 0;
5897     weight = 0;
5898     int nHeight = GetLastBlockHeight() + 1;
5899     int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(nHeight);
5900     std::map<COutPoint, uint32_t> immatureStakes = locked_chain.getImmatureStakes();
5901     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
5902     {
5903         const uint256& wtxid = it->first;
5904         const CWalletTx* pcoin = &(*it).second;
5905         int nDepth = pcoin->GetDepthInMainChain();
5906 
5907         if (nDepth < 1)
5908             continue;
5909 
5910         uint256 hashBlock = pcoin->m_confirm.hashBlock;
5911         bool fHasProofOfDelegation = false;
5912         CBlockIndex* blockIndex = LookupBlockIndex(hashBlock);
5913         if(!blockIndex)
5914             continue;
5915         fHasProofOfDelegation = blockIndex->HasProofOfDelegation();
5916 
5917         bool isImature = pcoin->GetBlocksToMaturity() == 0;
5918         for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
5919         {
5920             bool OK = false;
5921             PKHash keyId = ExtractPublicKeyHash(pcoin->tx->vout[i].scriptPubKey, &OK);
5922             if(OK && keyId == staker)
5923             {
5924                 isminetype mine = IsMine(pcoin->tx->vout[i]);
5925                   if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
5926                     !IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue > 0))
5927                 {
5928                       CAmount nValue = pcoin->tx->vout[i].nValue;
5929                       if(isImature)
5930                       {
5931                           balance += nValue;
5932                           if(nDepth >= coinbaseMaturity && nValue >= DEFAULT_STAKING_MIN_UTXO_VALUE)
5933                           {
5934                               COutPoint prevout = COutPoint(pcoin->tx->GetHash(), i);
5935                               if(immatureStakes.find(prevout) == immatureStakes.end())
5936                               {
5937                                   weight += nValue;
5938                               }
5939                           }
5940                       }
5941                       else if(pcoin->IsCoinStake() && fHasProofOfDelegation)
5942                       {
5943                           stake += nValue;
5944                       }
5945                 }
5946             }
5947         }
5948     }
5949 }
5950 
updateHaveCoinSuperStaker(const std::set<std::pair<const CWalletTx *,unsigned int>> & setCoins)5951 void CWallet::updateHaveCoinSuperStaker(const std::set<std::pair<const CWalletTx *, unsigned int> > &setCoins)
5952 {
5953     LOCK(cs_wallet);
5954     m_have_coin_superstaker.clear();
5955 
5956     COutPoint prevout;
5957     CAmount nValueRet = 0;
5958     for (const auto& entry : mapSuperStaker) {
5959         if(GetCoinSuperStaker(setCoins, PKHash(entry.second.stakerAddress), prevout, nValueRet))
5960         {
5961             m_have_coin_superstaker[entry.second.stakerAddress] = true;
5962         }
5963     }
5964 }
5965 
UpdateMinerStakeCache(bool fStakeCache,const std::vector<COutPoint> & prevouts,CBlockIndex * pindexPrev)5966 void CWallet::UpdateMinerStakeCache(bool fStakeCache, const std::vector<COutPoint> &prevouts, CBlockIndex *pindexPrev )
5967 {
5968     if(minerStakeCache.size() > prevouts.size() + 100){
5969         minerStakeCache.clear();
5970     }
5971 
5972     if(fStakeCache)
5973     {
5974         for(const COutPoint &prevoutStake : prevouts)
5975         {
5976             boost::this_thread::interruption_point();
5977             CacheKernel(minerStakeCache, prevoutStake, pindexPrev, ::ChainstateActive().CoinsTip());
5978         }
5979         if(!fHasMinerStakeCache) fHasMinerStakeCache = true;
5980     }
5981 }
5982 
CleanCoinStake()5983 void CWallet::CleanCoinStake()
5984 {
5985     auto locked_chain = chain().lock();
5986     LOCK(cs_wallet);
5987     // Search the coinstake transactions and abandon transactions that are not confirmed in the blocks
5988     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
5989     {
5990         const CWalletTx* wtx = &(*it).second;
5991         if (wtx && wtx->m_confirm.hashBlock.IsNull() && wtx->m_confirm.nIndex <= 0)
5992         {
5993             // Wallets need to refund inputs when disconnecting coinstake
5994             const CTransaction& tx = *(wtx->tx);
5995             if (tx.IsCoinStake() && IsFromMe(tx) && !wtx->isAbandoned())
5996             {
5997                 WalletLogPrintf("%s: Revert coinstake tx %s\n", __func__, wtx->GetHash().ToString());
5998                 DisableTransaction(tx);
5999             }
6000         }
6001     }
6002 }
6003 
AvailableCoinsForStaking(const std::vector<uint256> & maturedTx,size_t from,size_t to,const std::map<COutPoint,uint32_t> & immatureStakes,std::vector<std::pair<const CWalletTx *,unsigned int>> & vCoins,std::map<COutPoint,CScriptCache> * insertScriptCache) const6004 void CWallet::AvailableCoinsForStaking(const std::vector<uint256>& maturedTx, size_t from, size_t to, const std::map<COutPoint, uint32_t>& immatureStakes, std::vector<std::pair<const CWalletTx *, unsigned int> >& vCoins, std::map<COutPoint, CScriptCache>* insertScriptCache) const
6005 {
6006     for(size_t i = from; i < to; i++)
6007     {
6008         std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(maturedTx[i]);
6009         if(it == mapWallet.end()) continue;
6010         const uint256& wtxid = it->first;
6011         const CWalletTx* pcoin = &(*it).second;
6012         for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
6013             isminetype mine = IsMine(pcoin->tx->vout[i]);
6014             if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
6015                 !IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue > 0) &&
6016                 // Check if the staking coin is dust
6017                 pcoin->tx->vout[i].nValue >= m_staker_min_utxo_size)
6018             {
6019                 // Get the script data for the coin
6020                 COutPoint prevout = COutPoint(pcoin->GetHash(), i);
6021                 const CScriptCache& scriptCache = GetScriptCache(prevout, pcoin->tx->vout[i].scriptPubKey, insertScriptCache);
6022 
6023                 // Check that the script is not a contract script
6024                 if(scriptCache.contract || !scriptCache.keyIdOk)
6025                     continue;
6026 
6027                 // Check that the address is not delegated to other staker
6028                 if(m_my_delegations.find(scriptCache.keyId) != m_my_delegations.end())
6029                     continue;
6030 
6031                 // Check prevout maturity
6032                 if(immatureStakes.find(prevout) == immatureStakes.end())
6033                 {
6034                     // Check if script is spendable
6035                     bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && scriptCache.solvable);
6036                     if(spendable)
6037                         vCoins.push_back(std::make_pair(pcoin, i));
6038                 }
6039             }
6040         }
6041     }
6042 }
6043 
SelectCoinsForStaking(interfaces::Chain::Lock & locked_chain,CAmount & nTargetValue,std::set<std::pair<const CWalletTx *,unsigned int>> & setCoinsRet,CAmount & nValueRet) const6044 bool CWallet::SelectCoinsForStaking(interfaces::Chain::Lock &locked_chain, CAmount &nTargetValue, std::set<std::pair<const CWalletTx *, unsigned int> > &setCoinsRet, CAmount &nValueRet) const
6045 {
6046     std::vector<std::pair<const CWalletTx *, unsigned int> > vCoins;
6047     vCoins.clear();
6048 
6049     int nHeight = GetLastBlockHeight() + 1;
6050     int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(nHeight);
6051     std::map<COutPoint, uint32_t> immatureStakes = locked_chain.getImmatureStakes();
6052     std::vector<uint256> maturedTx;
6053     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
6054     {
6055         // Check the cached data for available coins for the tx
6056         const CWalletTx* pcoin = &(*it).second;
6057         const CAmount tx_credit_mine{pcoin->GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | ISMINE_NO)};
6058         if(tx_credit_mine == 0)
6059             continue;
6060 
6061         const uint256& wtxid = it->first;
6062         int nDepth = pcoin->GetDepthInMainChain();
6063 
6064         if (nDepth < 1)
6065             continue;
6066 
6067         if (nDepth < coinbaseMaturity)
6068             continue;
6069 
6070         if (pcoin->GetBlocksToMaturity() > 0)
6071             continue;
6072 
6073         maturedTx.push_back(wtxid);
6074     }
6075 
6076     size_t listSize = maturedTx.size();
6077     int numThreads = std::min(m_num_threads, (int)listSize);
6078     if(numThreads < 2)
6079     {
6080         AvailableCoinsForStaking(maturedTx, 0, listSize, immatureStakes, vCoins, nullptr);
6081     }
6082     else
6083     {
6084         size_t chunk = listSize / numThreads;
6085         for(int i = 0; i < numThreads; i++)
6086         {
6087             size_t from = i * chunk;
6088             size_t to = i == (numThreads -1) ? listSize : from + chunk;
6089             threads.create_thread([this, from, to, &maturedTx, &immatureStakes, &vCoins]{
6090                 std::vector<std::pair<const CWalletTx *, unsigned int> > tmpCoins;
6091                 std::map<COutPoint, CScriptCache> tmpInsertScriptCache;
6092                 AvailableCoinsForStaking(maturedTx, from, to, immatureStakes, tmpCoins, &tmpInsertScriptCache);
6093 
6094                 LOCK(cs_worker);
6095                 vCoins.insert(vCoins.end(), tmpCoins.begin(), tmpCoins.end());
6096                 if((int32_t)prevoutScriptCache.size() > m_staker_max_utxo_script_cache)
6097                 {
6098                     prevoutScriptCache.clear();
6099                 }
6100                 prevoutScriptCache.insert(tmpInsertScriptCache.begin(), tmpInsertScriptCache.end());
6101             });
6102         }
6103         threads.join_all();
6104     }
6105 
6106     setCoinsRet.clear();
6107     nValueRet = 0;
6108 
6109     for(const std::pair<const CWalletTx*,unsigned int> &output : vCoins)
6110     {
6111         const CWalletTx *pcoin = output.first;
6112         int i = output.second;
6113 
6114         // Stop if we've chosen enough inputs
6115         if (nValueRet >= nTargetValue)
6116             break;
6117 
6118         int64_t n = pcoin->tx->vout[i].nValue;
6119 
6120         std::pair<int64_t,std::pair<const CWalletTx*,unsigned int> > coin = std::make_pair(n,std::make_pair(pcoin, i));
6121 
6122         if (n >= nTargetValue)
6123         {
6124             // If input value is greater or equal to target then simply insert
6125             // it into the current subset and exit
6126             setCoinsRet.insert(coin.second);
6127             nValueRet += coin.first;
6128             break;
6129         }
6130         else if (n < nTargetValue + CENT)
6131         {
6132             setCoinsRet.insert(coin.second);
6133             nValueRet += coin.first;
6134         }
6135     }
6136 
6137     return true;
6138 }
6139 
AvailableDelegateCoinsForStaking(const std::vector<uint160> & delegations,size_t from,size_t to,int32_t height,const std::map<COutPoint,uint32_t> & immatureStakes,const std::map<uint256,CSuperStakerInfo> & mapStakers,std::vector<std::pair<COutPoint,CAmount>> & vUnsortedDelegateCoins,std::map<uint160,CAmount> & mDelegateWeight) const6140 bool CWallet::AvailableDelegateCoinsForStaking(const std::vector<uint160>& delegations, size_t from, size_t to, int32_t height, const std::map<COutPoint, uint32_t>& immatureStakes,  const std::map<uint256, CSuperStakerInfo>& mapStakers, std::vector<std::pair<COutPoint,CAmount>>& vUnsortedDelegateCoins, std::map<uint160, CAmount> &mDelegateWeight) const
6141 {
6142     for(size_t i = from; i < to; i++)
6143     {
6144         std::map<uint160, Delegation>::const_iterator it = m_delegations_staker.find(delegations[i]);
6145         if(it == m_delegations_staker.end()) continue;
6146 
6147         const PKHash& keyid = PKHash(it->first);
6148         const Delegation* delegation = &(*it).second;
6149 
6150         // Set default delegate stake weight
6151         CAmount weight = 0;
6152         mDelegateWeight[it->first] = weight;
6153 
6154         // Get super staker custom configuration
6155         CAmount staking_min_utxo_value = m_staking_min_utxo_value;
6156         uint8_t staking_min_fee = m_staking_min_fee;
6157         for (std::map<uint256, CSuperStakerInfo>::const_iterator it=mapStakers.begin(); it!=mapStakers.end(); it++)
6158         {
6159             if(it->second.stakerAddress == delegation->staker)
6160             {
6161                 CSuperStakerInfo info = it->second;
6162                 if(info.fCustomConfig)
6163                 {
6164                     staking_min_utxo_value = info.nMinDelegateUtxo;
6165                     staking_min_fee = info.nMinFee;
6166                 }
6167             }
6168         }
6169 
6170         // Check for min staking fee
6171         if(delegation->fee < staking_min_fee)
6172             continue;
6173 
6174         // Decode address
6175         uint256 hashBytes;
6176         int type = 0;
6177         if (!DecodeIndexKey(EncodeDestination(keyid), hashBytes, type)) {
6178             return error("Invalid address");
6179         }
6180 
6181         // Get address utxos
6182         std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
6183         if (!GetAddressUnspent(hashBytes, type, unspentOutputs)) {
6184             throw error("No information available for address");
6185         }
6186 
6187         // Add the utxos to the list if they are mature and at least the minimum value
6188         int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(height + 1);
6189         for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator i=unspentOutputs.begin(); i!=unspentOutputs.end(); i++) {
6190 
6191             int nDepth = height - i->second.blockHeight + 1;
6192             if (nDepth < coinbaseMaturity)
6193                 continue;
6194 
6195             if(i->second.satoshis < staking_min_utxo_value)
6196                 continue;
6197 
6198             COutPoint prevout = COutPoint(i->first.txhash, i->first.index);
6199             if(immatureStakes.find(prevout) == immatureStakes.end())
6200             {
6201                 vUnsortedDelegateCoins.push_back(std::make_pair(prevout, i->second.satoshis));
6202                 weight+= i->second.satoshis;
6203             }
6204         }
6205 
6206         // Update delegate stake weight
6207         mDelegateWeight[it->first] = weight;
6208     }
6209 
6210     return true;
6211 }
6212 
SelectDelegateCoinsForStaking(interfaces::Chain::Lock & locked_chain,std::vector<COutPoint> & setDelegateCoinsRet,std::map<uint160,CAmount> & mDelegateWeight) const6213 bool CWallet::SelectDelegateCoinsForStaking(interfaces::Chain::Lock &locked_chain, std::vector<COutPoint> &setDelegateCoinsRet, std::map<uint160, CAmount> &mDelegateWeight) const
6214 {
6215     AssertLockHeld(cs_main);
6216     AssertLockHeld(cs_wallet);
6217 
6218     setDelegateCoinsRet.clear();
6219 
6220     std::vector<std::pair<COutPoint,CAmount>> vUnsortedDelegateCoins;
6221 
6222     int32_t const height = locked_chain.getHeight().get_value_or(-1);
6223     if (height == -1) {
6224         return error("Invalid blockchain height");
6225     }
6226 
6227     std::map<COutPoint, uint32_t> immatureStakes = locked_chain.getImmatureStakes();
6228     std::map<uint256, CSuperStakerInfo> mapStakers = mapSuperStaker;
6229 
6230     std::vector<uint160> delegations;
6231     for (std::map<uint160, Delegation>::const_iterator it = m_delegations_staker.begin(); it != m_delegations_staker.end(); ++it)
6232     {
6233         delegations.push_back(it->first);
6234     }
6235     size_t listSize = delegations.size();
6236     int numThreads = std::min(m_num_threads, (int)listSize);
6237     bool ret = true;
6238     if(numThreads < 2)
6239     {
6240         ret = AvailableDelegateCoinsForStaking(delegations, 0, listSize, height, immatureStakes, mapStakers, vUnsortedDelegateCoins, mDelegateWeight);
6241     }
6242     else
6243     {
6244         size_t chunk = listSize / numThreads;
6245         for(int i = 0; i < numThreads; i++)
6246         {
6247             size_t from = i * chunk;
6248             size_t to = i == (numThreads -1) ? listSize : from + chunk;
6249             threads.create_thread([this, from, to, height, &delegations, &immatureStakes, &mapStakers, &ret, &vUnsortedDelegateCoins, &mDelegateWeight]{
6250                 std::vector<std::pair<COutPoint,CAmount>> tmpUnsortedDelegateCoins;
6251                 std::map<uint160, CAmount> tmpDelegateWeight;
6252                 bool tmpRet = AvailableDelegateCoinsForStaking(delegations, from, to, height, immatureStakes, mapStakers, tmpUnsortedDelegateCoins, tmpDelegateWeight);
6253 
6254                 LOCK(cs_worker);
6255                 ret &= tmpRet;
6256                 vUnsortedDelegateCoins.insert(vUnsortedDelegateCoins.end(), tmpUnsortedDelegateCoins.begin(), tmpUnsortedDelegateCoins.end());
6257                 mDelegateWeight.insert(tmpDelegateWeight.begin(), tmpDelegateWeight.end());
6258             });
6259         }
6260         threads.join_all();
6261     }
6262 
6263     std::sort(vUnsortedDelegateCoins.begin(), vUnsortedDelegateCoins.end(), valueUtxoSort);
6264 
6265     for(auto utxo : vUnsortedDelegateCoins){
6266         setDelegateCoinsRet.push_back(utxo.first);
6267     }
6268 
6269     vUnsortedDelegateCoins.clear();
6270 
6271     return ret;
6272 }
6273 
AvailableAddress(const std::vector<uint256> & maturedTx,size_t from,size_t to,std::map<uint160,bool> & mapAddress,std::map<COutPoint,CScriptCache> * insertScriptCache) const6274 void CWallet::AvailableAddress(const std::vector<uint256> &maturedTx, size_t from, size_t to, std::map<uint160, bool> &mapAddress, std::map<COutPoint, CScriptCache> *insertScriptCache) const
6275 {
6276     for(size_t i = from; i < to; i++)
6277     {
6278         std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(maturedTx[i]);
6279         if(it == mapWallet.end()) continue;
6280         const uint256& wtxid = it->first;
6281         const CWalletTx* pcoin = &(*it).second;
6282         for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
6283             isminetype mine = IsMine(pcoin->tx->vout[i]);
6284             if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
6285                 !IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue > 0) &&
6286                 // Check if the staking coin is dust
6287                 pcoin->tx->vout[i].nValue >= m_staker_min_utxo_size)
6288             {
6289                 // Get the script data for the coin
6290                 COutPoint prevout = COutPoint(pcoin->GetHash(), i);
6291                 const CScriptCache& scriptCache = GetScriptCache(prevout, pcoin->tx->vout[i].scriptPubKey, insertScriptCache);
6292 
6293                 // Check that the script is not a contract script
6294                 if(scriptCache.contract || !scriptCache.keyIdOk)
6295                     continue;
6296 
6297                 bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && scriptCache.solvable);
6298                 if(spendable)
6299                 {
6300                     if(mapAddress.find(scriptCache.keyId) == mapAddress.end())
6301                     {
6302                         mapAddress[scriptCache.keyId] = true;
6303                     }
6304                 }
6305             }
6306         }
6307     }
6308 }
6309 
SelectAddress(interfaces::Chain::Lock & locked_chain,std::map<uint160,bool> & mapAddress) const6310 void CWallet::SelectAddress(interfaces::Chain::Lock &locked_chain, std::map<uint160, bool> &mapAddress) const
6311 {
6312     std::vector<uint256> maturedTx;
6313     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
6314     {
6315         // Check the cached data for available coins for the tx
6316         const CWalletTx* pcoin = &(*it).second;
6317         const CAmount tx_credit_mine{pcoin->GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | ISMINE_NO)};
6318         if(tx_credit_mine == 0)
6319             continue;
6320 
6321         const uint256& wtxid = it->first;
6322         int nDepth = pcoin->GetDepthInMainChain();
6323 
6324         if (nDepth < 1)
6325             continue;
6326 
6327         if (pcoin->GetBlocksToMaturity() > 0)
6328             continue;
6329 
6330         maturedTx.push_back(wtxid);
6331     }
6332 
6333     size_t listSize = maturedTx.size();
6334     int numThreads = std::min(m_num_threads, (int)listSize);
6335     if(numThreads < 2)
6336     {
6337         AvailableAddress(maturedTx, 0, listSize, mapAddress, nullptr);
6338     }
6339     else
6340     {
6341         size_t chunk = listSize / numThreads;
6342         for(int i = 0; i < numThreads; i++)
6343         {
6344             size_t from = i * chunk;
6345             size_t to = i == (numThreads -1) ? listSize : from + chunk;
6346             threads.create_thread([this, from, to, &maturedTx, &mapAddress]{
6347                 std::map<uint160, bool> tmpAddresses;
6348                 std::map<COutPoint, CScriptCache> tmpInsertScriptCache;
6349                 AvailableAddress(maturedTx, from, to, tmpAddresses, &tmpInsertScriptCache);
6350 
6351                 LOCK(cs_worker);
6352                 mapAddress.insert(tmpAddresses.begin(), tmpAddresses.end());
6353                 if((int32_t)prevoutScriptCache.size() > m_staker_max_utxo_script_cache)
6354                 {
6355                     prevoutScriptCache.clear();
6356                 }
6357                 prevoutScriptCache.insert(tmpInsertScriptCache.begin(), tmpInsertScriptCache.end());
6358             });
6359         }
6360         threads.join_all();
6361     }
6362 }
6363