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