Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 The Bitcoin developers
3 : // Copyright (c) 2014-2015 The Dash developers
4 : // Copyright (c) 2015-2022 The PIVX Core developers
5 : // Distributed under the MIT software license, see the accompanying
6 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 :
8 : #include "optional.h"
9 : #include "validation.h"
10 : #if defined(HAVE_CONFIG_H)
11 : #include "config/pivx-config.h"
12 : #endif
13 :
14 : #include "wallet/wallet.h"
15 :
16 : #include "checkpoints.h"
17 : #include "coincontrol.h"
18 : #include "evo/providertx.h"
19 : #include "guiinterfaceutil.h"
20 : #include "policy/policy.h"
21 : #include "sapling/key_io_sapling.h"
22 : #include "script/sign.h"
23 : #include "scheduler.h"
24 : #include "shutdown.h"
25 : #include "spork.h"
26 : #include "util/validation.h"
27 : #include "utilmoneystr.h"
28 : #include "wallet/fees.h"
29 :
30 : #include <future>
31 : #include <boost/algorithm/string/replace.hpp>
32 :
33 : std::vector<CWalletRef> vpwallets;
34 : /**
35 : * Settings
36 : */
37 : CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
38 : CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
39 : unsigned int nTxConfirmTarget = 1;
40 : bool bdisableSystemnotifications = false; // Those bubbles can be annoying and slow down the UI when you get lots of trx
41 : bool fPayAtLeastCustomFee = true;
42 : bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
43 :
44 : /**
45 : * Fees smaller than this (in upiv) are considered zero fee (for transaction creation)
46 : * We are ~100 times smaller then bitcoin now (2015-06-23), set minTxFee 10 times higher
47 : * so it's still 10 times lower comparing to bitcoin.
48 : * Override with -mintxfee
49 : */
50 : CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
51 :
52 : /**
53 : * minimum accpeted value for stake split threshold
54 : */
55 : CAmount CWallet::minStakeSplitThreshold = DEFAULT_MIN_STAKE_SPLIT_THRESHOLD;
56 :
57 : const uint256 CWalletTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
58 :
59 : /** @defgroup mapWallet
60 : *
61 : * @{
62 : */
63 :
64 : struct CompareValueOnly {
65 1595958 : bool operator()(const std::pair<CAmount, std::pair<const CWalletTx*, unsigned int> >& t1,
66 : const std::pair<CAmount, std::pair<const CWalletTx*, unsigned int> >& t2) const
67 : {
68 1555120 : return t1.first < t2.first;
69 : }
70 : };
71 :
72 0 : std::string COutput::ToString() const
73 : {
74 0 : return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
75 : }
76 :
77 : class CAffectedKeysVisitor : public boost::static_visitor<void>
78 : {
79 : private:
80 : const CKeyStore& keystore;
81 : std::vector<CKeyID>& vKeys;
82 :
83 : public:
84 1135032 : CAffectedKeysVisitor(const CKeyStore& keystoreIn, std::vector<CKeyID>& vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
85 :
86 1135052 : void Process(const CScript& script)
87 : {
88 1135052 : txnouttype type;
89 2270094 : std::vector<CTxDestination> vDest;
90 1135052 : int nRequired;
91 1135052 : if (ExtractDestinations(script, type, vDest, nRequired)) {
92 2265416 : for (const CTxDestination& dest : vDest)
93 1132783 : boost::apply_visitor(*this, dest);
94 : }
95 1135052 : }
96 :
97 1132723 : void operator()(const CKeyID& keyId)
98 : {
99 1132723 : if (keystore.HaveKey(keyId))
100 1127952 : vKeys.push_back(keyId);
101 1132723 : }
102 :
103 10 : void operator()(const CExchangeKeyID& keyId) {
104 10 : if (keystore.HaveKey(keyId))
105 4 : vKeys.push_back(keyId);
106 10 : }
107 :
108 46 : void operator()(const CScriptID& scriptId)
109 : {
110 46 : CScript script;
111 46 : if (keystore.GetCScript(scriptId, script))
112 13 : Process(script);
113 46 : }
114 :
115 0 : void operator()(const CNoDestination& none) {}
116 : };
117 :
118 1135032 : std::vector<CKeyID> CWallet::GetAffectedKeys(const CScript& spk)
119 : {
120 1135032 : std::vector<CKeyID> ret;
121 0 : std::vector<CKeyID> vAffected;
122 1135032 : CAffectedKeysVisitor(*this, vAffected).Process(spk);
123 2262994 : for (const CKeyID& keyid : vAffected) {
124 1127952 : ret.emplace_back(keyid);
125 : }
126 2262964 : return ret;
127 : }
128 :
129 : ////////////////////////////////////////////////////////////////////////////////////////////////////
130 :
131 : ///////////////////////////////////////////////////////////////////////////////////////////////////
132 :
133 235 : bool CWallet::SetupSPKM(bool newKeypool, bool memOnly)
134 : {
135 235 : if (m_spk_man->SetupGeneration(newKeypool, true, memOnly)) {
136 235 : LogPrintf("%s : spkm setup completed\n", __func__);
137 235 : return ActivateSaplingWallet(memOnly);
138 : }
139 : return false;
140 : }
141 :
142 237 : bool CWallet::ActivateSaplingWallet(bool memOnly)
143 : {
144 237 : if (m_sspk_man->SetupGeneration(m_spk_man->GetHDChain().GetID(), true, memOnly)) {
145 237 : LogPrintf("%s : sapling spkm setup completed\n", __func__);
146 : // Just to be triple sure, if the version isn't updated, set it.
147 237 : if (!SetMinVersion(WalletFeature::FEATURE_SAPLING)) {
148 0 : LogPrintf("%s : ERROR: wallet cannot upgrade to sapling features. Try to upgrade using the 'upgradewallet' RPC command\n", __func__);
149 0 : return false;
150 : }
151 : return true;
152 : }
153 : return false;
154 : }
155 :
156 66 : bool CWallet::IsHDEnabled() const
157 : {
158 66 : return m_spk_man->IsHDEnabled();
159 : }
160 :
161 0 : bool CWallet::IsSaplingUpgradeEnabled() const
162 : {
163 0 : return m_sspk_man->IsEnabled();
164 : }
165 :
166 1004436 : const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
167 : {
168 1004436 : LOCK(cs_wallet);
169 1004436 : std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
170 1004436 : if (it == mapWallet.end())
171 : return nullptr;
172 1004336 : return &(it->second);
173 : }
174 :
175 0 : std::vector<CWalletTx> CWallet::getWalletTxs()
176 : {
177 0 : LOCK(cs_wallet);
178 0 : std::vector<CWalletTx> result;
179 0 : result.reserve(mapWallet.size());
180 0 : for (const auto& entry : mapWallet) {
181 0 : result.emplace_back(entry.second);
182 : }
183 0 : return result;
184 : }
185 :
186 9 : CallResult<CTxDestination> CWallet::getNewAddress(const std::string& label)
187 : {
188 18 : return getNewAddress(label, AddressBook::AddressBookPurpose::RECEIVE);
189 : }
190 :
191 0 : CallResult<CTxDestination> CWallet::getNewStakingAddress(const std::string& label)
192 : {
193 0 : return getNewAddress(label, AddressBook::AddressBookPurpose::COLD_STAKING, CChainParams::Base58Type::STAKING_ADDRESS);
194 : }
195 :
196 2288 : CallResult<CTxDestination> CWallet::getNewAddress(const std::string& addressLabel, const std::string purpose,
197 : const CChainParams::Base58Type addrType)
198 : {
199 4576 : LOCK(cs_wallet);
200 :
201 : // Refill keypool if wallet is unlocked
202 2288 : if (!IsLocked())
203 2274 : TopUpKeyPool();
204 :
205 2288 : uint8_t type = (addrType == CChainParams::Base58Type::STAKING_ADDRESS ? HDChain::ChangeType::STAKING : HDChain::ChangeType::EXTERNAL);
206 2288 : CPubKey newKey;
207 : // Get a key
208 2288 : if (!GetKeyFromPool(newKey, type)) {
209 : // inform the user to top-up the keypool or unlock the wallet
210 6 : return CallResult<CTxDestination>(std::string(
211 3 : _("Keypool ran out, please call keypoolrefill first, or unlock the wallet.")));
212 : }
213 2285 : CKeyID keyID = newKey.GetID();
214 :
215 2285 : if (!SetAddressBook(keyID, addressLabel, purpose))
216 0 : throw std::runtime_error("CWallet::getNewAddress() : SetAddressBook failed");
217 :
218 2285 : return CallResult<CTxDestination>(CTxDestination(keyID));
219 : }
220 :
221 0 : int64_t CWallet::GetKeyCreationTime(const CWDestination& dest)
222 : {
223 0 : auto shieldDest = Standard::GetShieldedDestination(dest);
224 0 : auto transpDest = Standard::GetTransparentDestination(dest);
225 0 : return shieldDest ? GetKeyCreationTime(*shieldDest) : transpDest ? GetKeyCreationTime(*transpDest) : 0;
226 : }
227 :
228 0 : int64_t CWallet::GetKeyCreationTime(CPubKey pubkey)
229 : {
230 0 : return mapKeyMetadata[pubkey.GetID()].nCreateTime;
231 : }
232 :
233 0 : int64_t CWallet::GetKeyCreationTime(const CTxDestination& address)
234 : {
235 0 : const CKeyID* keyID = boost::get<CKeyID>(&address);
236 0 : if (keyID) {
237 0 : CPubKey keyRet;
238 0 : if (GetPubKey(*keyID, keyRet)) {
239 0 : return GetKeyCreationTime(keyRet);
240 : }
241 : }
242 : return 0;
243 : }
244 :
245 0 : int64_t CWallet::GetKeyCreationTime(const libzcash::SaplingPaymentAddress& address)
246 : {
247 0 : libzcash::SaplingIncomingViewingKey ivk;
248 0 : return GetSaplingIncomingViewingKey(address, ivk) ?
249 0 : GetSaplingScriptPubKeyMan()->GetKeyCreationTime(ivk) : 0;
250 : }
251 :
252 11871 : bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey& pubkey)
253 : {
254 11871 : AssertLockHeld(cs_wallet); // mapKeyMetadata
255 11871 : if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
256 : return false;
257 :
258 : // TODO: Move the follow block entirely inside the spkm (including WriteKey to AddKeyPubKeyWithDB)
259 : // check if we need to remove from watch-only
260 23742 : CScript script;
261 11871 : script = GetScriptForDestination(pubkey.GetID());
262 11871 : if (HaveWatchOnly(script))
263 1 : RemoveWatchOnly(script);
264 :
265 11871 : script = GetScriptForRawPubKey(pubkey);
266 11871 : if (HaveWatchOnly(script)) {
267 0 : RemoveWatchOnly(script);
268 : }
269 :
270 11871 : if (!IsCrypted()) {
271 35592 : return WalletBatch(*database).WriteKey(
272 : pubkey,
273 11864 : secret.GetPrivKey(),
274 23728 : mapKeyMetadata[pubkey.GetID()]);
275 : }
276 : return true;
277 : }
278 :
279 1746 : bool CWallet::AddCryptedKey(const CPubKey& vchPubKey,
280 : const std::vector<unsigned char>& vchCryptedSecret)
281 : {
282 1746 : if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
283 : return false;
284 1746 : {
285 3492 : LOCK(cs_wallet);
286 1746 : if (encrypted_batch)
287 778 : return encrypted_batch->WriteCryptedKey(vchPubKey,
288 : vchCryptedSecret,
289 1556 : mapKeyMetadata[vchPubKey.GetID()]);
290 : else
291 968 : return WalletBatch(*database).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
292 : }
293 : return false;
294 : }
295 :
296 8389 : bool CWallet::LoadKeyMetadata(const CPubKey& pubkey, const CKeyMetadata& meta)
297 : {
298 8389 : AssertLockHeld(cs_wallet); // mapKeyMetadata
299 8389 : if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
300 501 : nTimeFirstKey = meta.nCreateTime;
301 :
302 8389 : mapKeyMetadata[pubkey.GetID()] = meta;
303 8389 : return true;
304 : }
305 :
306 602 : bool CWallet::LoadCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret)
307 : {
308 602 : return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
309 : }
310 :
311 : /**
312 : * Update wallet first key creation time. This should be called whenever keys
313 : * are added to the wallet, with the oldest key creation time.
314 : */
315 13 : void CWallet::UpdateTimeFirstKey(int64_t nCreateTime)
316 : {
317 13 : AssertLockHeld(cs_wallet);
318 13 : if (nCreateTime <= 1) {
319 : // Cannot determine birthday information, so set the wallet birthday to
320 : // the beginning of time.
321 9 : nTimeFirstKey = 1;
322 4 : } else if (!nTimeFirstKey || nCreateTime < nTimeFirstKey) {
323 4 : nTimeFirstKey = nCreateTime;
324 : }
325 13 : }
326 :
327 15 : bool CWallet::AddCScript(const CScript& redeemScript)
328 : {
329 15 : if (!CCryptoKeyStore::AddCScript(redeemScript))
330 : return false;
331 15 : return WalletBatch(*database).WriteCScript(Hash160(redeemScript), redeemScript);
332 : }
333 :
334 2 : bool CWallet::LoadCScript(const CScript& redeemScript)
335 : {
336 : /* A sanity check was added in pull #3843 to avoid adding redeemScripts
337 : * that never can be redeemed. However, old wallets may still contain
338 : * these. Do not add them to the wallet and warn. */
339 4 : if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) {
340 0 : std::string strAddr = EncodeDestination(CScriptID(redeemScript));
341 0 : LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
342 0 : __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
343 0 : return true;
344 : }
345 :
346 2 : return CCryptoKeyStore::AddCScript(redeemScript);
347 : }
348 :
349 41 : bool CWallet::AddWatchOnly(const CScript& dest)
350 : {
351 41 : if (!CCryptoKeyStore::AddWatchOnly(dest))
352 : return false;
353 41 : nTimeFirstKey = 1; // No birthday information for watch-only keys.
354 41 : NotifyWatchonlyChanged(true);
355 41 : return WalletBatch(*database).WriteWatchOnly(dest);
356 : }
357 :
358 1 : bool CWallet::RemoveWatchOnly(const CScript& dest)
359 : {
360 1 : AssertLockHeld(cs_wallet);
361 1 : if (!CCryptoKeyStore::RemoveWatchOnly(dest))
362 : return false;
363 1 : if (!HaveWatchOnly())
364 1 : NotifyWatchonlyChanged(false);
365 1 : if (!WalletBatch(*database).EraseWatchOnly(dest))
366 0 : return false;
367 :
368 : return true;
369 : }
370 :
371 11 : bool CWallet::LoadWatchOnly(const CScript& dest)
372 : {
373 11 : return CCryptoKeyStore::AddWatchOnly(dest);
374 : }
375 :
376 25 : bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool stakingOnly)
377 : {
378 25 : CCrypter crypter;
379 50 : CKeyingMaterial vMasterKey;
380 :
381 25 : {
382 25 : LOCK(cs_wallet);
383 27 : for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys) {
384 25 : if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
385 23 : return false;
386 25 : if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
387 2 : continue; // try another master key
388 23 : if (Unlock(vMasterKey)) {
389 23 : fWalletUnlockStaking = stakingOnly;
390 23 : return true;
391 : }
392 : }
393 : }
394 2 : return false;
395 : }
396 :
397 23 : bool CWallet::Lock()
398 : {
399 23 : if (!SetCrypted())
400 : return false;
401 :
402 23 : {
403 23 : LOCK(cs_KeyStore);
404 38 : vMasterKey.clear();
405 : }
406 :
407 23 : NotifyStatusChanged(this);
408 23 : return true;
409 : }
410 :
411 24 : bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn)
412 : {
413 24 : {
414 24 : LOCK(cs_KeyStore);
415 24 : if (!SetCrypted())
416 0 : return false;
417 :
418 24 : bool keyPass = false;
419 24 : bool keyFail = false;
420 24 : CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
421 1404 : for (; mi != mapCryptedKeys.end(); ++mi) {
422 1396 : const CPubKey& vchPubKey = (*mi).second.first;
423 1396 : const std::vector<unsigned char>& vchCryptedSecret = (*mi).second.second;
424 2776 : CKey key;
425 1396 : if (!DecryptKey(vMasterKeyIn, vchCryptedSecret, vchPubKey, key)) {
426 : keyFail = true;
427 16 : break;
428 : }
429 1396 : keyPass = true;
430 1396 : if (fDecryptionThoroughlyChecked)
431 : break;
432 : }
433 :
434 24 : if (keyPass && keyFail) {
435 0 : LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
436 0 : throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
437 : }
438 :
439 24 : if (keyFail || !keyPass)
440 : return false;
441 :
442 : // Sapling
443 24 : if (!UnlockSaplingKeys(vMasterKeyIn, fDecryptionThoroughlyChecked)) {
444 : // If Sapling key encryption fail, let's unencrypt the rest of the keys
445 0 : LogPrintf("Sapling wallet unlock keys failed\n");
446 0 : throw std::runtime_error("Error unlocking wallet: some Sapling keys decrypt but not all. Your wallet file may be corrupt.");
447 : }
448 :
449 24 : vMasterKey = vMasterKeyIn;
450 24 : fDecryptionThoroughlyChecked = true;
451 : }
452 :
453 24 : NotifyStatusChanged(this);
454 24 : return true;
455 : }
456 :
457 1 : bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
458 : {
459 1 : bool fWasLocked = IsLocked();
460 2 : SecureString strOldWalletPassphraseFinal = strOldWalletPassphrase;
461 :
462 1 : {
463 1 : LOCK(cs_wallet);
464 1 : Lock();
465 :
466 1 : CCrypter crypter;
467 1 : CKeyingMaterial vMasterKey;
468 1 : for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys) {
469 1 : if (!crypter.SetKeyFromPassphrase(strOldWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
470 1 : return false;
471 1 : if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
472 : return false;
473 1 : if (Unlock(vMasterKey)) {
474 1 : int64_t nStartTime = GetTimeMillis();
475 1 : crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
476 1 : pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
477 :
478 1 : nStartTime = GetTimeMillis();
479 1 : crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
480 1 : pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
481 :
482 1 : if (pMasterKey.second.nDeriveIterations < 25000)
483 0 : pMasterKey.second.nDeriveIterations = 25000;
484 :
485 1 : LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
486 :
487 1 : if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
488 : return false;
489 1 : if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
490 : return false;
491 1 : WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second);
492 1 : if (fWasLocked)
493 1 : Lock();
494 :
495 1 : return true;
496 : }
497 : }
498 : }
499 :
500 0 : return false;
501 : }
502 :
503 42129 : void CWallet::ChainTipAdded(const CBlockIndex *pindex,
504 : const CBlock *pblock,
505 : SaplingMerkleTree saplingTree)
506 : {
507 42129 : IncrementNoteWitnesses(pindex, pblock, saplingTree);
508 42129 : m_sspk_man->UpdateSaplingNullifierNoteMapForBlock(pblock);
509 42129 : }
510 :
511 327 : void CWallet::SetBestChain(const CBlockLocator& loc)
512 : {
513 327 : WalletBatch batch(*database);
514 327 : SetBestChainInternal(batch, loc);
515 327 : }
516 :
517 327 : void CWallet::SetBestChainInternal(WalletBatch& batch, const CBlockLocator& loc)
518 : {
519 327 : if (!batch.TxnBegin()) {
520 : // This needs to be done atomically, so don't do it at all
521 0 : LogPrintf("%s: Couldn't start atomic write\n", __func__);
522 0 : return;
523 : }
524 :
525 : // Store the best block
526 327 : if (!batch.WriteBestBlock(loc)) {
527 0 : LogPrintf("SetBestChain(): Failed to write best block, aborting atomic write\n");
528 0 : batch.TxnAbort();
529 0 : return;
530 : }
531 :
532 : // For performance reasons, we update the witnesses data here and not when each transaction arrives
533 6478 : for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
534 12302 : auto wtx = wtxItem.second;
535 : // We skip transactions for which mapSaplingNoteData is empty.
536 : // This covers transactions that have no Sapling data
537 : // (i.e. are purely transparent), as well as shielding and unshielding
538 : // transactions in which we only have transparent addresses involved.
539 6151 : if (!wtx.mapSaplingNoteData.empty()) {
540 : // Sanity check
541 33 : if (!wtx.tx->isSaplingVersion()) {
542 0 : LogPrintf("SetBestChain(): ERROR, Invalid tx version found with sapling data\n");
543 0 : batch.TxnAbort();
544 0 : uiInterface.ThreadSafeMessageBox(
545 0 : _("A fatal internal error occurred, see debug.log for details"),
546 : "Error", CClientUIInterface::MSG_ERROR);
547 0 : StartShutdown();
548 0 : return;
549 : }
550 :
551 33 : if (!batch.WriteTx(wtx)) {
552 0 : LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n");
553 0 : batch.TxnAbort();
554 : return;
555 : }
556 : }
557 : }
558 :
559 : // Store sapling witness cache size
560 327 : if (m_sspk_man->nWitnessCacheNeedsUpdate) {
561 327 : if (!batch.WriteWitnessCacheSize(m_sspk_man->nWitnessCacheSize)) {
562 0 : LogPrintf("%s: Failed to write nWitnessCacheSize\n", __func__);
563 0 : batch.TxnAbort();
564 0 : return;
565 : }
566 : }
567 :
568 327 : if (!batch.TxnCommit()) {
569 : // Couldn't commit all to db, but in-memory state is fine
570 0 : LogPrintf("%s: Couldn't commit atomic write\n", __func__);
571 0 : return;
572 : }
573 :
574 : // Reset cache if the commit succeed and is needed.
575 327 : if (m_sspk_man->nWitnessCacheNeedsUpdate) {
576 327 : m_sspk_man->nWitnessCacheNeedsUpdate = false;
577 : }
578 : }
579 :
580 11886 : bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
581 : {
582 23772 : LOCK(cs_wallet); // nWalletVersion
583 11886 : if (nWalletVersion >= nVersion)
584 : return true;
585 :
586 : // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
587 238 : if (fExplicit && nVersion > nWalletMaxVersion)
588 0 : nVersion = FEATURE_LATEST;
589 :
590 238 : nWalletVersion = nVersion;
591 :
592 238 : if (nVersion > nWalletMaxVersion)
593 238 : nWalletMaxVersion = nVersion;
594 :
595 238 : {
596 238 : WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database);
597 238 : if (nWalletVersion > 40000)
598 238 : batch->WriteMinVersion(nWalletVersion);
599 238 : if (!batch_in)
600 476 : delete batch;
601 : }
602 :
603 : return true;
604 : }
605 :
606 203 : bool CWallet::SetMaxVersion(int nVersion)
607 : {
608 203 : LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
609 : // cannot downgrade below current version
610 203 : if (nWalletVersion > nVersion)
611 : return false;
612 :
613 203 : nWalletMaxVersion = nVersion;
614 :
615 203 : return true;
616 : }
617 :
618 397 : std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
619 : {
620 397 : std::set<uint256> result;
621 397 : AssertLockHeld(cs_wallet);
622 :
623 397 : std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
624 397 : if (it == mapWallet.end())
625 : return result;
626 395 : const CWalletTx& wtx = it->second;
627 :
628 395 : std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
629 :
630 840 : for (const CTxIn& txin : wtx.tx->vin) {
631 445 : if (mapTxSpends.count(txin.prevout) <= 1 || wtx.tx->HasZerocoinSpendInputs())
632 436 : continue; // No conflict if zero or one spends
633 9 : range = mapTxSpends.equal_range(txin.prevout);
634 27 : for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
635 18 : result.insert(_it->second);
636 : }
637 :
638 : // Sapling
639 395 : if (HasSaplingSPKM()) {
640 395 : m_sspk_man->GetConflicts(wtx, result);
641 : }
642 :
643 : return result;
644 : }
645 :
646 144 : void CWallet::SyncMetaDataN(std::pair<TxSpendMap<uint256>::iterator, TxSpendMap<uint256>::iterator> range)
647 : {
648 144 : SyncMetaData<uint256>(range);
649 144 : }
650 :
651 : template <class T>
652 207717 : void CWallet::SyncMetaData(std::pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
653 : {
654 : // We want all the wallet transactions in range to have the same metadata as
655 : // the oldest (smallest nOrderPos).
656 : // So: find smallest nOrderPos:
657 :
658 207717 : int nMinOrderPos = std::numeric_limits<int>::max();
659 207717 : const CWalletTx* copyFrom = nullptr;
660 440006 : for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it) {
661 232289 : const CWalletTx* wtx = &mapWallet.at(it->second);
662 232289 : int n = wtx->nOrderPos;
663 232289 : if (n < nMinOrderPos) {
664 207719 : nMinOrderPos = n;
665 207719 : copyFrom = wtx;
666 : }
667 : }
668 :
669 207717 : if (!copyFrom) {
670 : return;
671 : }
672 :
673 : // Now copy data from copyFrom to rest:
674 440006 : for (auto it = range.first; it != range.second; ++it) {
675 232289 : const uint256& hash = it->second;
676 232289 : CWalletTx* copyTo = &mapWallet.at(hash);
677 232289 : if (copyFrom == copyTo) continue;
678 : assert(copyFrom && "Oldest wallet transaction in range assumed to have been found.");
679 : //if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
680 24338 : copyTo->mapValue = copyFrom->mapValue;
681 24338 : copyTo->vOrderForm = copyFrom->vOrderForm;
682 : // fTimeReceivedIsTxTime not copied on purpose
683 : // nTimeReceived not copied on purpose
684 24338 : copyTo->nTimeSmart = copyFrom->nTimeSmart;
685 24338 : copyTo->fFromMe = copyFrom->fFromMe;
686 : // nOrderPos not copied on purpose
687 : // cached members not copied on purpose
688 : }
689 : }
690 :
691 963 : const CKeyingMaterial& CWallet::GetEncryptionKey() const
692 : {
693 963 : return vMasterKey;
694 : }
695 :
696 11507 : bool CWallet::HasEncryptionKeys() const
697 : {
698 11507 : return !mapMasterKeys.empty();
699 : }
700 :
701 8831 : ScriptPubKeyMan* CWallet::GetScriptPubKeyMan() const
702 : {
703 8831 : return m_spk_man.get();
704 : }
705 :
706 1543914 : bool CWallet::HasSaplingSPKM() const
707 : {
708 1543914 : return GetSaplingScriptPubKeyMan()->IsEnabled();
709 : }
710 :
711 2 : bool CWallet::IsSaplingSpent(const SaplingOutPoint& op) const
712 : {
713 2 : return m_sspk_man->IsSaplingSpent(op);
714 : }
715 :
716 : /**
717 : * Outpoint is spent if any non-conflicted transaction
718 : * spends it:
719 : */
720 9652734 : bool CWallet::IsSpent(const COutPoint& outpoint) const
721 : {
722 9652734 : AssertLockHeld(cs_wallet);
723 9652734 : std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
724 9652734 : range = mapTxSpends.equal_range(outpoint);
725 9653109 : for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
726 5740154 : const uint256& wtxid = it->second;
727 5740154 : std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
728 5740154 : if (mit != mapWallet.end()) {
729 5740154 : bool fConflicted;
730 5740154 : const int nDepth = mit->second.GetDepthAndMempool(fConflicted);
731 : // not in mempool txes can spend coins only if not coinstakes
732 5740154 : const bool fConflictedCoinstake = fConflicted && mit->second.IsCoinStake();
733 5740154 : if (nDepth > 0 || (nDepth == 0 && !mit->second.isAbandoned() && !fConflictedCoinstake) )
734 5739779 : return true; // Spent
735 : }
736 : }
737 3912955 : return false;
738 : }
739 :
740 9639819 : bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
741 : {
742 9639819 : return IsSpent(COutPoint(hash, n));
743 : }
744 :
745 207573 : void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
746 : {
747 207573 : mapTxSpends.emplace(outpoint, wtxid);
748 207573 : setLockedCoins.erase(outpoint);
749 :
750 207573 : std::pair<TxSpends::iterator, TxSpends::iterator> range;
751 207573 : range = mapTxSpends.equal_range(outpoint);
752 207573 : SyncMetaData<COutPoint>(range);
753 207573 : }
754 :
755 125882 : void CWallet::AddToSpends(const uint256& wtxid)
756 : {
757 125882 : auto it = mapWallet.find(wtxid);
758 125882 : assert(it != mapWallet.end());
759 125882 : CWalletTx& thisTx = it->second;
760 125882 : if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
761 18821 : return;
762 :
763 314634 : for (const CTxIn& txin : thisTx.tx->vin)
764 207573 : AddToSpends(txin.prevout, wtxid);
765 :
766 107061 : if (CanSupportFeature(FEATURE_SAPLING) && thisTx.tx->sapData) {
767 107205 : for (const SpendDescription &spend : thisTx.tx->sapData->vShieldedSpend) {
768 144 : GetSaplingScriptPubKeyMan()->AddToSaplingSpends(spend.nullifier, wtxid);
769 : }
770 : }
771 : }
772 :
773 7 : bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
774 : {
775 7 : if (IsCrypted())
776 : return false;
777 :
778 14 : CKeyingMaterial vMasterKey;
779 :
780 7 : vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
781 7 : GetStrongRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
782 :
783 14 : CMasterKey kMasterKey;
784 :
785 7 : kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
786 7 : GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
787 :
788 14 : CCrypter crypter;
789 7 : int64_t nStartTime = GetTimeMillis();
790 7 : crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
791 7 : kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
792 :
793 7 : nStartTime = GetTimeMillis();
794 7 : crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
795 7 : kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
796 :
797 7 : if (kMasterKey.nDeriveIterations < 25000)
798 0 : kMasterKey.nDeriveIterations = 25000;
799 :
800 7 : LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
801 :
802 7 : if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
803 : return false;
804 7 : if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
805 : return false;
806 :
807 7 : {
808 7 : LOCK(cs_wallet);
809 7 : mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
810 7 : assert(!encrypted_batch);
811 7 : encrypted_batch = new WalletBatch(*database);
812 7 : if (!encrypted_batch->TxnBegin()) {
813 0 : delete encrypted_batch;
814 0 : encrypted_batch = nullptr;
815 0 : return false;
816 : }
817 7 : encrypted_batch->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
818 :
819 :
820 7 : if (!EncryptKeys(vMasterKey) || (m_sspk_man->IsEnabled() && !m_sspk_man->EncryptSaplingKeys(vMasterKey))) {
821 0 : encrypted_batch->TxnAbort();
822 0 : delete encrypted_batch;
823 : // We now probably have half of our keys encrypted in memory, and half not...
824 : // die and let the user reload their unencrypted wallet.
825 0 : assert(false);
826 : }
827 :
828 : // Encryption was introduced in version 0.4.0
829 7 : SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true);
830 :
831 7 : if (!encrypted_batch->TxnCommit()) {
832 0 : delete encrypted_batch;
833 : // We now have keys encrypted in memory, but not on disk...
834 : // die to avoid confusion and let the user reload their unencrypted wallet.
835 0 : assert(false);
836 : }
837 :
838 14 : delete encrypted_batch;
839 7 : encrypted_batch = nullptr;
840 :
841 7 : Lock();
842 7 : Unlock(strWalletPassphrase);
843 : // if we are using HD, replace the HD seed with a new one
844 7 : if (m_spk_man->IsHDEnabled()) {
845 7 : if (!m_spk_man->SetupGeneration(true, true)) {
846 : return false;
847 : }
848 : }
849 7 : Lock();
850 :
851 : // Need to completely rewrite the wallet file; if we don't, bdb might keep
852 : // bits of the unencrypted private key in slack space in the database file.
853 7 : database->Rewrite();
854 :
855 : // BDB seems to have a bad habit of writing old data into
856 : // slack space in .dat files; that is bad if the old data is
857 : // unencrypted private keys. So:
858 7 : database->ReloadDbEnv();
859 :
860 : }
861 7 : NotifyStatusChanged(this);
862 :
863 : return true;
864 : }
865 :
866 119200 : int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
867 : {
868 119200 : AssertLockHeld(cs_wallet); // nOrderPosNext
869 119200 : int64_t nRet = nOrderPosNext++;
870 119200 : if (batch) {
871 119200 : batch->WriteOrderPosNext(nOrderPosNext);
872 : } else {
873 0 : WalletBatch(*database).WriteOrderPosNext(nOrderPosNext);
874 : }
875 119200 : return nRet;
876 : }
877 :
878 0 : bool CWallet::IsKeyUsed(const CPubKey& vchPubKey) const
879 : {
880 0 : if (vchPubKey.IsValid()) {
881 0 : const CScript& scriptPubKey = GetScriptForDestination(vchPubKey.GetID());
882 0 : for (const auto& entry : mapWallet) {
883 0 : const CWalletTx& wtx = entry.second;
884 0 : for (const CTxOut& txout : wtx.tx->vout)
885 0 : if (txout.scriptPubKey == scriptPubKey)
886 0 : return true;
887 : }
888 : }
889 : return false;
890 : }
891 :
892 1073 : void CWallet::MarkDirty()
893 : {
894 1073 : {
895 1073 : LOCK(cs_wallet);
896 5651 : for (std::pair<const uint256, CWalletTx> & item : mapWallet)
897 4578 : item.second.MarkDirty();
898 : }
899 1073 : }
900 :
901 396555 : bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
902 : {
903 793110 : LOCK(cs_wallet);
904 793110 : WalletBatch batch(*database, "r+", fFlushOnClose);
905 396555 : const uint256& hash = wtxIn.GetHash();
906 :
907 : // Inserts only if not already there, returns tx inserted or tx found
908 396555 : std::pair<std::map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.emplace(hash, wtxIn);
909 396555 : CWalletTx& wtx = (*ret.first).second;
910 396555 : wtx.BindWallet(this);
911 : // Sapling
912 396555 : m_sspk_man->UpdateNullifierNoteMapWithTx(wtx);
913 396555 : bool fInsertedNew = ret.second;
914 396555 : if (fInsertedNew) {
915 119200 : wtx.nTimeReceived = GetAdjustedTime();
916 119200 : wtx.nOrderPos = IncOrderPosNext(&batch);
917 119200 : wtxOrdered.emplace(wtx.nOrderPos, &wtx);
918 119200 : wtx.UpdateTimeSmart();
919 119200 : AddToSpends(hash);
920 : }
921 :
922 396555 : bool fUpdated = false;
923 396555 : if (!fInsertedNew) {
924 277355 : if (wtxIn.m_confirm.status != wtx.m_confirm.status) {
925 216137 : wtx.m_confirm.status = wtxIn.m_confirm.status;
926 216137 : wtx.m_confirm.nIndex = wtxIn.m_confirm.nIndex;
927 216137 : wtx.m_confirm.hashBlock = wtxIn.m_confirm.hashBlock;
928 216137 : wtx.m_confirm.block_height = wtxIn.m_confirm.block_height;
929 216137 : wtx.UpdateTimeSmart();
930 : fUpdated = true;
931 : } else {
932 61218 : assert(wtx.m_confirm.nIndex == wtxIn.m_confirm.nIndex);
933 61218 : assert(wtx.m_confirm.hashBlock == wtxIn.m_confirm.hashBlock);
934 61218 : assert(wtx.m_confirm.block_height == wtxIn.m_confirm.block_height);
935 : }
936 277355 : if (HasSaplingSPKM() && m_sspk_man->UpdatedNoteData(wtxIn, wtx)) {
937 : fUpdated = true;
938 : }
939 277355 : if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) {
940 0 : wtx.fFromMe = wtxIn.fFromMe;
941 0 : fUpdated = true;
942 : }
943 : }
944 :
945 : //// debug print
946 734023 : LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
947 :
948 : // Write to disk
949 396555 : if (fInsertedNew || fUpdated) {
950 336442 : if (!batch.WriteTx(wtx))
951 : return false;
952 : }
953 :
954 : // Break debit/credit balance caches:
955 396555 : wtx.MarkDirty();
956 :
957 : // Notify UI of new or updated transaction
958 673910 : NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
959 :
960 : // notify an external script when a wallet transaction comes in or is updated
961 1189665 : std::string strCmd = gArgs.GetArg("-walletnotify", "");
962 :
963 396555 : if (!strCmd.empty()) {
964 73 : boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
965 146 : std::thread t(runCommand, strCmd);
966 73 : t.detach(); // thread runs free
967 : }
968 396555 : return true;
969 : }
970 :
971 : // Internal function for now, this will be part of a chain interface class in the future.
972 6526 : static Optional<int> getTipBlockHeight(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
973 : {
974 6526 : AssertLockHeld(cs_main);
975 :
976 6526 : CBlockIndex* pindex = LookupBlockIndex(hash);
977 12890 : if (pindex && chainActive.Contains(pindex)) {
978 6346 : return Optional<int>(pindex->nHeight);
979 : }
980 180 : return nullopt;
981 : }
982 :
983 6682 : bool CWallet::LoadToWallet(CWalletTx& wtxIn)
984 : {
985 13364 : LOCK2(cs_main, cs_wallet);
986 : // If tx hasn't been reorged out of chain while wallet being shutdown
987 : // change tx status to UNCONFIRMED and reset hashBlock/nIndex.
988 18226 : if (!wtxIn.m_confirm.hashBlock.IsNull()) {
989 6526 : Optional<int> block_height = getTipBlockHeight(wtxIn.m_confirm.hashBlock);
990 6526 : if (block_height) {
991 : // Update cached block height variable since it not stored in the
992 : // serialized transaction.
993 6346 : wtxIn.m_confirm.block_height = *block_height;
994 180 : } else if (wtxIn.isConflicted() || wtxIn.isConfirmed()) {
995 : // If tx block (or conflicting block) was reorged out of chain
996 : // while the wallet was shutdown, change tx status to UNCONFIRMED
997 : // and reset block height, hash, and index. ABANDONED tx don't have
998 : // associated blocks and don't need to be updated. The case where a
999 : // transaction was reorged out while online and then reconfirmed
1000 : // while offline is covered by the rescan logic.
1001 180 : wtxIn.setUnconfirmed();
1002 180 : wtxIn.m_confirm.hashBlock = UINT256_ZERO;
1003 180 : wtxIn.m_confirm.block_height = 0;
1004 180 : wtxIn.m_confirm.nIndex = 0;
1005 : }
1006 : }
1007 6682 : const uint256& hash = wtxIn.GetHash();
1008 6682 : CWalletTx& wtx = mapWallet.emplace(hash, wtxIn).first->second;
1009 6682 : wtx.BindWallet(this);
1010 : // Sapling
1011 6682 : m_sspk_man->UpdateNullifierNoteMapWithTx(wtx);
1012 6682 : wtxOrdered.emplace(wtx.nOrderPos, &wtx);
1013 6682 : AddToSpends(hash);
1014 13483 : for (const CTxIn& txin : wtx.tx->vin) {
1015 6801 : auto it = mapWallet.find(txin.prevout.hash);
1016 6801 : if (it != mapWallet.end()) {
1017 133 : CWalletTx& prevtx = it->second;
1018 133 : if (prevtx.isConflicted()) {
1019 0 : MarkConflicted(prevtx.m_confirm.hashBlock, prevtx.m_confirm.block_height, wtx.GetHash());
1020 : }
1021 : }
1022 : }
1023 13364 : return true;
1024 : }
1025 :
1026 647495 : bool CWallet::FindNotesDataAndAddMissingIVKToKeystore(const CTransaction& tx, Optional<mapSaplingNoteData_t>& saplingNoteData)
1027 : {
1028 647495 : auto saplingNoteDataAndAddressesToAdd = m_sspk_man->FindMySaplingNotes(tx);
1029 647495 : saplingNoteData = saplingNoteDataAndAddressesToAdd.first;
1030 1294986 : auto addressesToAdd = saplingNoteDataAndAddressesToAdd.second;
1031 : // Add my addresses
1032 647495 : for (const auto& addressToAdd : addressesToAdd) {
1033 0 : if (!m_sspk_man->AddSaplingIncomingViewingKey(addressToAdd.second, addressToAdd.first)) {
1034 0 : return false;
1035 : }
1036 : }
1037 647495 : return true;
1038 : }
1039 :
1040 1810 : void CWallet::AddExternalNotesDataToTx(CWalletTx& wtx) const
1041 : {
1042 1810 : if (HasSaplingSPKM() && wtx.tx->IsShieldedTx()) {
1043 1810 : const uint256& txId = wtx.GetHash();
1044 : // Add the external outputs.
1045 1810 : SaplingOutPoint op {txId, 0};
1046 3796 : for (unsigned int i = 0; i < wtx.tx->sapData->vShieldedOutput.size(); i++) {
1047 1986 : op.n = i;
1048 3873 : if (wtx.mapSaplingNoteData.count(op)) continue; // internal output
1049 198 : auto recovered = GetSaplingScriptPubKeyMan()->TryToRecoverNote(wtx, op);
1050 99 : if (recovered) {
1051 : // Always true for 'IsFromMe' transactions
1052 95 : wtx.mapSaplingNoteData[op].address = recovered->second;
1053 95 : wtx.mapSaplingNoteData[op].amount = recovered->first.value();
1054 95 : const auto& memo = recovered->first.memo();
1055 : // don't save empty memo (starting with 0xF6)
1056 95 : if (memo[0] < 0xF6) {
1057 99 : wtx.mapSaplingNoteData[op].memo = memo;
1058 : }
1059 : }
1060 : }
1061 : }
1062 1810 : }
1063 :
1064 : /**
1065 : * Add a transaction to the wallet, or update it. pIndex and posInBlock should
1066 : * be set when the transaction was known to be included in a block. When
1067 : * pIndex == nullptr, then wallet state is not updated in AddToWallet, but
1068 : * notifications happen and cached balances are marked dirty.
1069 : *
1070 : * If fUpdate is true, existing transactions will be updated.
1071 : * TODO: One exception to this is that the abandoned state is cleared under the
1072 : * assumption that any further notification of a transaction that was considered
1073 : * abandoned is an indication that it is not safe to be considered abandoned.
1074 : * Abandoned state should probably be more carefully tracked via different
1075 : * posInBlock signals or by checking mempool presence when necessary.
1076 : */
1077 647707 : bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CWalletTx::Confirmation& confirm, bool fUpdate)
1078 : {
1079 647707 : const CTransaction& tx = *ptx;
1080 647707 : {
1081 647707 : AssertLockHeld(cs_wallet);
1082 :
1083 1295416 : if (!confirm.hashBlock.IsNull() && !tx.HasZerocoinSpendInputs() && !tx.IsCoinBase()) {
1084 909198 : for (const CTxIn& txin : tx.vin) {
1085 588830 : std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
1086 894131 : while (range.first != range.second) {
1087 305301 : if (range.first->second != tx.GetHash()) {
1088 48 : LogPrintf("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);
1089 12 : MarkConflicted(confirm.hashBlock, confirm.block_height, range.first->second);
1090 : }
1091 894131 : range.first++;
1092 : }
1093 : }
1094 : }
1095 :
1096 647707 : bool fExisted = mapWallet.count(tx.GetHash()) != 0;
1097 647707 : if (fExisted && !fUpdate) return false;
1098 :
1099 : // Check tx for Sapling notes
1100 647707 : Optional<mapSaplingNoteData_t> saplingNoteData {nullopt};
1101 647707 : if (HasSaplingSPKM()) {
1102 647489 : if (!FindNotesDataAndAddMissingIVKToKeystore(tx, saplingNoteData)) {
1103 395104 : return false; // error adding incoming viewing key.
1104 : }
1105 : }
1106 :
1107 : // If this is a ProRegTx and the wallet owns the collateral, lock the corresponding coin
1108 647707 : LockIfMyCollateral(ptx);
1109 :
1110 647707 : bool isFromMe = IsFromMe(ptx);
1111 647707 : if (fExisted || IsMine(ptx) || isFromMe || (saplingNoteData && !saplingNoteData->empty())) {
1112 :
1113 : /* Check if any keys in the wallet keypool that were supposed to be unused
1114 : * have appeared in a new transaction. If so, remove those keys from the keypool.
1115 : * This can happen when restoring an old wallet backup that does not contain
1116 : * the mostly recently created transactions from newer versions of the wallet.
1117 : */
1118 :
1119 : // loop though all outputs
1120 1530141 : for (const CTxOut& txout: tx.vout) {
1121 1135032 : m_spk_man->MarkUnusedAddresses(txout.scriptPubKey);
1122 : }
1123 :
1124 790208 : CWalletTx wtx(this, MakeTransactionRef(tx));
1125 395104 : if (wtx.tx->IsShieldedTx()) {
1126 1955 : if (saplingNoteData && !saplingNoteData->empty()) {
1127 1896 : wtx.SetSaplingNoteData(*saplingNoteData);
1128 : }
1129 :
1130 : // Add external notes info if we are sending
1131 1955 : if (isFromMe) AddExternalNotesDataToTx(wtx);
1132 : }
1133 :
1134 : // Block disconnection override an abandoned tx as unconfirmed
1135 : // which means user may have to call abandontransaction again
1136 395104 : wtx.m_confirm = confirm;
1137 :
1138 395104 : return AddToWallet(wtx, false);
1139 : }
1140 : }
1141 252603 : return false;
1142 : }
1143 :
1144 6 : bool CWallet::AbandonTransaction(const uint256& hashTx)
1145 : {
1146 12 : LOCK(cs_wallet);
1147 :
1148 12 : WalletBatch batch(*database, "r+");
1149 :
1150 12 : std::set<uint256> todo;
1151 6 : std::set<uint256> done;
1152 :
1153 : // Can't mark abandoned if confirmed or in mempool
1154 6 : auto it = mapWallet.find(hashTx);
1155 6 : assert(it != mapWallet.end());
1156 6 : CWalletTx& origtx = it->second;
1157 6 : if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
1158 : return false;
1159 : }
1160 :
1161 5 : todo.insert(hashTx);
1162 :
1163 12 : while (!todo.empty()) {
1164 7 : uint256 now = *todo.begin();
1165 7 : todo.erase(now);
1166 7 : done.insert(now);
1167 7 : auto it2 = mapWallet.find(now);
1168 7 : assert(it2 != mapWallet.end());
1169 7 : CWalletTx& wtx = it2->second;
1170 7 : int currentconfirm = wtx.GetDepthInMainChain();
1171 : // If the orig tx was not in block, none of its spends can be
1172 7 : assert(currentconfirm <= 0);
1173 : // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
1174 7 : if (currentconfirm == 0 && !wtx.isAbandoned()) {
1175 : // If the orig tx was not in block/mempool, none of its spends can be in mempool
1176 7 : assert(!wtx.InMempool());
1177 7 : wtx.setAbandoned();
1178 7 : wtx.MarkDirty();
1179 7 : batch.WriteTx(wtx);
1180 7 : NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED);
1181 : // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
1182 7 : TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1183 8 : while (iter != mapTxSpends.end() && iter->first.hash == now) {
1184 2 : if (!done.count(iter->second)) {
1185 2 : todo.insert(iter->second);
1186 : }
1187 9 : iter++;
1188 : }
1189 : // If a transaction changes 'conflicted' state, that changes the balance
1190 : // available of the outputs it spends. So force those to be recomputed
1191 14 : for (const CTxIn& txin : wtx.tx->vin) {
1192 7 : auto _it = mapWallet.find(txin.prevout.hash);
1193 7 : if (_it != mapWallet.end()) {
1194 7 : _it->second.MarkDirty();
1195 : }
1196 : }
1197 : }
1198 : }
1199 :
1200 : return true;
1201 : }
1202 :
1203 12 : void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
1204 : {
1205 24 : LOCK(cs_wallet);
1206 :
1207 12 : int conflictconfirms = (m_last_block_processed_height - conflicting_height + 1) * -1;
1208 : // If number of conflict confirms cannot be determined, this means
1209 : // that the block is still unknown or not yet part of the main chain,
1210 : // for example when loading the wallet during a reindex. Do nothing in that
1211 : // case.
1212 12 : if (conflictconfirms >= 0)
1213 0 : return;
1214 :
1215 : // Do not flush the wallet here for performance reasons
1216 24 : WalletBatch batch(*database, "r+", false);
1217 :
1218 24 : std::set<uint256> todo;
1219 12 : std::set<uint256> done;
1220 :
1221 12 : todo.insert(hashTx);
1222 :
1223 26 : while (!todo.empty()) {
1224 14 : uint256 now = *todo.begin();
1225 14 : todo.erase(now);
1226 14 : done.insert(now);
1227 14 : auto it = mapWallet.find(now);
1228 14 : assert(it != mapWallet.end());
1229 14 : CWalletTx& wtx = it->second;
1230 14 : int currentconfirm = wtx.GetDepthInMainChain();
1231 14 : if (conflictconfirms < currentconfirm) {
1232 : // Block is 'more conflicted' than current confirm; update.
1233 : // Mark transaction as conflicted with this block.
1234 13 : wtx.m_confirm.nIndex = 0;
1235 13 : wtx.m_confirm.hashBlock = hashBlock;
1236 13 : wtx.m_confirm.block_height = conflicting_height;
1237 13 : wtx.setConflicted();
1238 13 : wtx.MarkDirty();
1239 13 : batch.WriteTx(wtx);
1240 : // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
1241 13 : TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
1242 13 : while (iter != mapTxSpends.end() && iter->first.hash == now) {
1243 2 : if (!done.count(iter->second)) {
1244 2 : todo.insert(iter->second);
1245 : }
1246 15 : iter++;
1247 : }
1248 : // If a transaction changes 'conflicted' state, that changes the balance
1249 : // available of the outputs it spends. So force those to be recomputed
1250 28 : for (const CTxIn& txin : wtx.tx->vin) {
1251 15 : auto _it = mapWallet.find(txin.prevout.hash);
1252 15 : if (_it != mapWallet.end()) {
1253 12 : _it->second.MarkDirty();
1254 : }
1255 : }
1256 : }
1257 : }
1258 : }
1259 :
1260 559149 : void CWallet::SyncTransaction(const CTransactionRef& ptx, const CWalletTx::Confirmation& confirm)
1261 : {
1262 559149 : if (!AddToWalletIfInvolvingMe(ptx, confirm, true)) {
1263 : return; // Not one of ours
1264 : }
1265 :
1266 386417 : MarkAffectedTransactionsDirty(*ptx);
1267 : }
1268 :
1269 171150 : void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx)
1270 : {
1271 171150 : LOCK(cs_wallet);
1272 342300 : CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
1273 171150 : SyncTransaction(ptx, confirm);
1274 :
1275 171150 : auto it = mapWallet.find(ptx->GetHash());
1276 171150 : if (it != mapWallet.end()) {
1277 155879 : it->second.fInMempool = true;
1278 : }
1279 171150 : }
1280 :
1281 300729 : void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx, MemPoolRemovalReason reason) {
1282 300729 : LOCK(cs_wallet);
1283 300729 : auto it = mapWallet.find(ptx->GetHash());
1284 300729 : if (it != mapWallet.end()) {
1285 170178 : it->second.fInMempool = false;
1286 : }
1287 : // Handle transactions that were removed from the mempool because they
1288 : // conflict with transactions in a newly connected block.
1289 300729 : if (reason == MemPoolRemovalReason::CONFLICT) {
1290 : // Call SyncNotifications, so external -walletnotify notifications will
1291 : // be triggered for these transactions. Set Status::UNCONFIRMED instead
1292 : // of Status::CONFLICTED for a few reasons:
1293 : //
1294 : // 1. The transactionRemovedFromMempool callback does not currently
1295 : // provide the conflicting block's hash and height, and for backwards
1296 : // compatibility reasons it may not be not safe to store conflicted
1297 : // wallet transactions with a null block hash. See
1298 : // https://github.com/bitcoin/bitcoin/pull/18600#discussion_r420195993.
1299 : // 2. For most of these transactions, the wallet's internal conflict
1300 : // detection in the blockConnected handler will subsequently call
1301 : // MarkConflicted and update them with CONFLICTED status anyway. This
1302 : // applies to any wallet transaction that has inputs spent in the
1303 : // block, or that has ancestors in the wallet with inputs spent by
1304 : // the block.
1305 : // 3. Longstanding behavior since the sync implementation in
1306 : // https://github.com/bitcoin/bitcoin/pull/9371 and the prior sync
1307 : // implementation before that was to mark these transactions
1308 : // unconfirmed rather than conflicted.
1309 : //
1310 : // Nothing described above should be seen as an unchangeable requirement
1311 : // when improving this code in the future. The wallet's heuristics for
1312 : // distinguishing between conflicted and unconfirmed transactions are
1313 : // imperfect, and could be improved in general, see
1314 : // https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
1315 6 : SyncTransaction(ptx, {CWalletTx::Status::UNCONFIRMED, /* block height */ 0, /* block hash */ {}, /* index */ 0});
1316 : }
1317 300729 : }
1318 :
1319 40375 : void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex)
1320 : {
1321 40375 : {
1322 80750 : LOCK2(cs_main, cs_wallet);
1323 :
1324 40375 : m_last_block_processed = pindex->GetBlockHash();
1325 40375 : m_last_block_processed_time = pindex->GetBlockTime();
1326 40375 : m_last_block_processed_height = pindex->nHeight;
1327 339698 : for (size_t index = 0; index < pblock->vtx.size(); index++) {
1328 299323 : CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, m_last_block_processed_height,
1329 299323 : m_last_block_processed, index);
1330 299323 : SyncTransaction(pblock->vtx[index], confirm);
1331 299323 : TransactionRemovedFromMempool(pblock->vtx[index], MemPoolRemovalReason::BLOCK);
1332 : }
1333 :
1334 : // Sapling: notify about the connected block
1335 : // Get prev block tree anchor
1336 40375 : CBlockIndex* pprev = pindex->pprev;
1337 80750 : SaplingMerkleTree oldSaplingTree;
1338 80552 : bool isSaplingActive = (pprev) != nullptr &&
1339 40177 : Params().GetConsensus().NetworkUpgradeActive(pprev->nHeight,
1340 40375 : Consensus::UPGRADE_V5_0);
1341 40375 : if (isSaplingActive) {
1342 19402 : assert(pcoinsTip->GetSaplingAnchorAt(pprev->hashFinalSaplingRoot, oldSaplingTree));
1343 : } else {
1344 41946 : assert(pcoinsTip->GetSaplingAnchorAt(SaplingMerkleTree::empty_root(), oldSaplingTree));
1345 : }
1346 :
1347 : // Sapling: Update cached incremental witnesses
1348 80750 : ChainTipAdded(pindex, pblock.get(), oldSaplingTree);
1349 : } // cs_wallet lock end
1350 :
1351 : // Auto-combine functionality
1352 : // If turned on Auto Combine will scan wallet for dust to combine
1353 : // Outside of the cs_wallet lock because requires cs_main for now
1354 : // due CreateTransaction/CommitTransaction dependency.
1355 40375 : if (fCombineDust && pindex->nHeight % frequency == 0) {
1356 1 : AutoCombineDust(g_connman.get());
1357 : }
1358 40375 : }
1359 :
1360 327 : void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const uint256& blockHash, int nBlockHeight, int64_t blockTime)
1361 : {
1362 327 : LOCK(cs_wallet);
1363 :
1364 : // At block disconnection, this will change an abandoned transaction to
1365 : // be unconfirmed, whether or not the transaction is added back to the mempool.
1366 : // User may have to call abandontransaction again. It may be addressed in the
1367 : // future with a stickier abandoned state or even removing abandontransaction call.
1368 327 : m_last_block_processed_height = nBlockHeight - 1;
1369 327 : m_last_block_processed_time = blockTime;
1370 327 : m_last_block_processed = blockHash;
1371 89000 : for (const CTransactionRef& ptx : pblock->vtx) {
1372 177346 : CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
1373 88673 : SyncTransaction(ptx, confirm);
1374 : }
1375 :
1376 327 : if (Params().GetConsensus().NetworkUpgradeActive(nBlockHeight, Consensus::UPGRADE_V5_0)) {
1377 : // Update Sapling cached incremental witnesses
1378 183 : m_sspk_man->DecrementNoteWitnesses(mapBlockIndex[blockHash]);
1379 183 : m_sspk_man->UpdateSaplingNullifierNoteMapForBlock(pblock.get());
1380 : }
1381 327 : }
1382 :
1383 4187 : void CWallet::BlockUntilSyncedToCurrentChain() {
1384 4187 : AssertLockNotHeld(cs_main);
1385 4187 : AssertLockNotHeld(cs_wallet);
1386 :
1387 4187 : {
1388 : // Skip the queue-draining stuff if we know we're caught up with
1389 : // chainActive.Tip()...
1390 : // We could also take cs_wallet here, and call m_last_block_processed
1391 : // protected by cs_wallet instead of cs_main, but as long as we need
1392 : // cs_main here anyway, its easier to just call it cs_main-protected.
1393 8374 : uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
1394 4187 : LOCK(cs_main);
1395 4187 : const CBlockIndex* initialChainTip = chainActive.Tip();
1396 8374 : if (!last_block_hash.IsNull() && initialChainTip &&
1397 4187 : last_block_hash == initialChainTip->GetBlockHash()) {
1398 6380 : return;
1399 : }
1400 : }
1401 :
1402 : // ...otherwise put a callback in the validation interface queue and wait
1403 : // for the queue to drain enough to execute it (indicating we are caught up
1404 : // at least with the time we entered this function).
1405 997 : SyncWithValidationInterfaceQueue();
1406 : }
1407 :
1408 386419 : void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx)
1409 : {
1410 : // If a transaction changes 'conflicted' state, that changes the balance
1411 : // available of the outputs it spends. So force those to be
1412 : // recomputed, also:
1413 1136922 : for (const CTxIn& txin : tx.vin) {
1414 750503 : if (!txin.IsZerocoinSpend()) {
1415 750503 : auto it = mapWallet.find(txin.prevout.hash);
1416 750503 : if (it != mapWallet.end()) {
1417 737252 : it->second.MarkDirty();
1418 : }
1419 : }
1420 : }
1421 :
1422 : // Sapling
1423 386419 : if (HasSaplingSPKM() && tx.IsShieldedTx()) {
1424 2053 : for (const SpendDescription &spend : tx.sapData->vShieldedSpend) {
1425 178 : const uint256& nullifier = spend.nullifier;
1426 178 : auto nit = m_sspk_man->mapSaplingNullifiersToNotes.find(nullifier);
1427 178 : if (nit != m_sspk_man->mapSaplingNullifiersToNotes.end()) {
1428 115 : auto it = mapWallet.find(nit->second.hash);
1429 115 : if (it != mapWallet.end()) {
1430 115 : it->second.MarkDirty();
1431 : }
1432 : }
1433 : }
1434 : }
1435 386419 : }
1436 :
1437 0 : void CWallet::EraseFromWallet(const uint256& hash)
1438 : {
1439 0 : {
1440 0 : LOCK(cs_wallet);
1441 0 : if (mapWallet.erase(hash))
1442 0 : WalletBatch(*database).EraseTx(hash);
1443 0 : LogPrintf("%s: Erased wtx %s from wallet\n", __func__, hash.GetHex());
1444 : }
1445 0 : return;
1446 : }
1447 :
1448 102 : isminetype CWallet::IsMine(const CTxIn& txin) const
1449 : {
1450 102 : {
1451 102 : LOCK(cs_wallet);
1452 102 : std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1453 102 : if (mi != mapWallet.end()) {
1454 0 : const CWalletTx& prev = (*mi).second;
1455 0 : if (txin.prevout.n < prev.tx->vout.size())
1456 0 : return IsMine(prev.tx->vout[txin.prevout.n]);
1457 : }
1458 : }
1459 102 : return ISMINE_NO;
1460 : }
1461 :
1462 0 : bool CWallet::IsUsed(const CTxDestination address) const
1463 : {
1464 0 : LOCK(cs_wallet);
1465 0 : CScript scriptPubKey = GetScriptForDestination(address);
1466 0 : if (!::IsMine(*this, scriptPubKey)) {
1467 : return false;
1468 : }
1469 :
1470 0 : for (const auto& it : mapWallet) {
1471 0 : const CWalletTx& wtx = it.second;
1472 0 : if (wtx.IsCoinBase()) {
1473 0 : continue;
1474 : }
1475 0 : for (const CTxOut& txout : wtx.tx->vout) {
1476 0 : if (txout.scriptPubKey == scriptPubKey)
1477 0 : return true;
1478 : }
1479 : }
1480 0 : return false;
1481 : }
1482 :
1483 0 : bool CWallet::IsUsed(const libzcash::SaplingPaymentAddress address) const
1484 : {
1485 0 : LOCK(cs_wallet);
1486 0 : if (!::IsMine(*this, address)) {
1487 : return false;
1488 : }
1489 :
1490 0 : for (const auto& it : mapWallet) {
1491 0 : const CWalletTx& wtx = it.second;
1492 0 : for (const auto& txout : wtx.mapSaplingNoteData) {
1493 0 : if (txout.second.address && *txout.second.address == address)
1494 0 : return true;
1495 : }
1496 : }
1497 0 : return false;
1498 : }
1499 :
1500 1186966 : CAmount CWallet::GetDebit(const CTxIn& txin, const isminefilter& filter) const
1501 : {
1502 1186966 : {
1503 1186966 : LOCK(cs_wallet);
1504 1186966 : std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1505 1186966 : if (mi != mapWallet.end()) {
1506 751466 : const CWalletTx& prev = (*mi).second;
1507 751466 : if (txin.prevout.n < prev.tx->vout.size())
1508 751466 : if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
1509 1479522 : return prev.tx->vout[txin.prevout.n].nValue;
1510 : }
1511 : }
1512 447208 : return 0;
1513 : }
1514 :
1515 239 : bool CWallet::IsChange(const CTxOut& txout) const
1516 : {
1517 : // TODO: fix handling of 'change' outputs. The assumption is that any
1518 : // payment to a script that is ours, but is not in the address book
1519 : // is change. That assumption is likely to break when we implement multisignature
1520 : // wallets that return change back into a multi-signature-protected address;
1521 : // a better way of identifying which outputs are 'the send' and which are
1522 : // 'the change' will need to be implemented (maybe extend CWalletTx to remember
1523 : // which output, if any, was change).
1524 239 : if (::IsMine(*this, txout.scriptPubKey)) {
1525 310 : CTxDestination address;
1526 155 : if (!ExtractDestination(txout.scriptPubKey, address))
1527 : return true;
1528 :
1529 155 : return IsChange(address);
1530 : }
1531 : return false;
1532 : }
1533 :
1534 647 : bool CWallet::IsChange(const CTxDestination& address) const
1535 : {
1536 : // Read the current assumptions in IsChange(const CTxOut&)
1537 : // this can definitely be different in the short future.
1538 1941 : return WITH_LOCK(cs_wallet, return !HasAddressBook(address));
1539 : }
1540 :
1541 472 : int64_t CWalletTx::GetTxTime() const
1542 : {
1543 472 : int64_t n = nTimeSmart;
1544 472 : return n ? n : nTimeReceived;
1545 : }
1546 :
1547 : /**
1548 : * Update smart timestamp for a transaction being added to the wallet.
1549 : *
1550 : * Logic:
1551 : * - If the transaction is not yet part of a block, assign its timestamp to the current time.
1552 : * - Else assign its timestamp to the block time
1553 : */
1554 335337 : void CWalletTx::UpdateTimeSmart()
1555 : {
1556 335337 : nTimeSmart = nTimeReceived;
1557 670674 : if (!m_confirm.hashBlock.IsNull()) {
1558 169344 : if (mapBlockIndex.count(m_confirm.hashBlock)) {
1559 169344 : nTimeSmart = mapBlockIndex.at(m_confirm.hashBlock)->GetBlockTime();
1560 : } else
1561 0 : LogPrintf("%s : found %s in block %s not in index\n", __func__, GetHash().ToString(), m_confirm.hashBlock.ToString());
1562 : }
1563 335337 : }
1564 :
1565 5208067 : CAmount CWalletTx::GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate) const
1566 : {
1567 5208067 : auto& amount = m_amounts[type];
1568 10410192 : if (recalculate || !amount.m_cached[filter]) {
1569 30008 : amount.Set(filter, type == DEBIT ? pwallet->GetDebit(tx, filter) : pwallet->GetCredit(*this, filter));
1570 : }
1571 5208067 : return amount.m_value[filter];
1572 : }
1573 :
1574 17 : bool CWalletTx::IsAmountCached(AmountType type, const isminefilter& filter) const
1575 : {
1576 17 : return m_amounts[type].m_cached[filter];
1577 : }
1578 :
1579 : //! filter decides which addresses will count towards the debit
1580 1519674 : CAmount CWalletTx::GetDebit(const isminefilter& filter) const
1581 : {
1582 1519674 : if (tx->vin.empty() && (tx->sapData && tx->sapData->vShieldedSpend.empty())) {
1583 : return 0;
1584 : }
1585 :
1586 1040874 : CAmount debit = 0;
1587 1040874 : if (filter & ISMINE_SPENDABLE) {
1588 1040533 : debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
1589 : }
1590 1040874 : if (filter & ISMINE_WATCH_ONLY) {
1591 1040240 : debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
1592 : }
1593 1040874 : if (filter & ISMINE_COLD) {
1594 1040410 : debit += GetCachableAmount(DEBIT, ISMINE_COLD);
1595 : }
1596 1040874 : if (filter & ISMINE_SPENDABLE_DELEGATED) {
1597 1040410 : debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE_DELEGATED);
1598 : }
1599 1040874 : if (filter & ISMINE_SPENDABLE_SHIELDED) {
1600 1040151 : debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE_SHIELDED);
1601 : }
1602 :
1603 : return debit;
1604 : }
1605 :
1606 0 : CAmount CWalletTx::GetColdStakingDebit(bool fUseCache) const
1607 : {
1608 0 : return GetCachableAmount(DEBIT, ISMINE_COLD, !fUseCache);
1609 : }
1610 :
1611 0 : CAmount CWalletTx::GetStakeDelegationDebit(bool fUseCache) const
1612 : {
1613 0 : return GetCachableAmount(DEBIT, ISMINE_SPENDABLE_DELEGATED, !fUseCache);
1614 : }
1615 :
1616 90 : CAmount CWalletTx::GetCredit(const isminefilter& filter, bool recalculate) const
1617 : {
1618 90 : CAmount credit = 0;
1619 90 : if (filter & ISMINE_SPENDABLE) {
1620 : // GetBalance can assume transactions in mapWallet won't change
1621 89 : credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE, recalculate);
1622 : }
1623 90 : if (filter & ISMINE_WATCH_ONLY) {
1624 9 : credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY, recalculate);
1625 : }
1626 90 : if (filter & ISMINE_COLD) {
1627 84 : credit += GetCachableAmount(CREDIT, ISMINE_COLD, recalculate);
1628 : }
1629 90 : if (filter & ISMINE_SPENDABLE_DELEGATED) {
1630 87 : credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE_DELEGATED, recalculate);
1631 : }
1632 90 : if (filter & ISMINE_SPENDABLE_SHIELDED) {
1633 88 : credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE_SHIELDED, recalculate);
1634 : }
1635 90 : return credit;
1636 : }
1637 :
1638 14062 : CAmount CWalletTx::GetImmatureCredit(bool fUseCache, const isminefilter& filter) const
1639 : {
1640 14062 : if (IsInMainChainImmature()) {
1641 5970 : return GetCachableAmount(IMMATURE_CREDIT, filter, !fUseCache);
1642 : }
1643 :
1644 : return 0;
1645 : }
1646 :
1647 465365 : CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const
1648 : {
1649 465365 : if (!pwallet)
1650 : return 0;
1651 :
1652 : // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
1653 930730 : bool allow_cache = filter == ISMINE_SPENDABLE || filter == ISMINE_WATCH_ONLY ||
1654 465365 : filter == ISMINE_SPENDABLE_SHIELDED || filter == ISMINE_WATCH_ONLY_SHIELDED;
1655 :
1656 : // Must wait until coinbase/coinstake is safely deep enough in the chain before valuing it
1657 465365 : if (GetBlocksToMaturity() > 0)
1658 : return 0;
1659 :
1660 431080 : if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
1661 99809 : return m_amounts[AVAILABLE_CREDIT].m_value[filter];
1662 : }
1663 :
1664 229260 : CAmount nCredit = 0;
1665 : // If the filter is only for shielded amounts, do not calculate the regular outputs
1666 229260 : if (filter != ISMINE_SPENDABLE_SHIELDED && filter != ISMINE_WATCH_ONLY_SHIELDED) {
1667 :
1668 229242 : const uint256& hashTx = GetHash();
1669 498610 : for (unsigned int i = 0; i < tx->vout.size(); i++) {
1670 269368 : if (!pwallet->IsSpent(hashTx, i)) {
1671 172295 : const CTxOut &txout = tx->vout[i];
1672 172295 : nCredit += pwallet->GetCredit(txout, filter);
1673 441663 : if (!Params().GetConsensus().MoneyRange(nCredit))
1674 0 : throw std::runtime_error(std::string(__func__) + " : value out of range");
1675 : }
1676 : }
1677 :
1678 : }
1679 :
1680 229260 : if (pwallet->HasSaplingSPKM()) {
1681 : // Can calculate the shielded available balance.
1682 229260 : if (filter & ISMINE_SPENDABLE_SHIELDED || filter & ISMINE_WATCH_ONLY_SHIELDED) {
1683 21360 : nCredit += pwallet->GetSaplingScriptPubKeyMan()->GetCredit(*this, filter, true);
1684 : }
1685 : }
1686 :
1687 229260 : if (allow_cache) {
1688 467569 : m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
1689 : }
1690 :
1691 : return nCredit;
1692 : }
1693 :
1694 139551 : CAmount CWalletTx::GetColdStakingCredit(bool fUseCache) const
1695 : {
1696 139551 : return GetAvailableCredit(fUseCache, ISMINE_COLD);
1697 : }
1698 :
1699 140072 : CAmount CWalletTx::GetStakeDelegationCredit(bool fUseCache) const
1700 : {
1701 140072 : return GetAvailableCredit(fUseCache, ISMINE_SPENDABLE_DELEGATED);
1702 : }
1703 :
1704 : // Return sum of locked coins
1705 138880 : CAmount CWalletTx::GetLockedCredit() const
1706 : {
1707 138880 : if (pwallet == 0)
1708 : return 0;
1709 :
1710 : // Must wait until coinbase is safely deep enough in the chain before valuing it
1711 138880 : if (IsCoinBase() && GetBlocksToMaturity() > 0)
1712 : return 0;
1713 :
1714 119972 : CAmount nCredit = 0;
1715 119972 : uint256 hashTx = GetHash();
1716 119972 : const CAmount collAmt = Params().GetConsensus().nMNCollateralAmt;
1717 274451 : for (unsigned int i = 0; i < tx->vout.size(); i++) {
1718 154479 : const CTxOut& txout = tx->vout[i];
1719 :
1720 : // Skip spent coins
1721 154479 : if (pwallet->IsSpent(hashTx, i)) continue;
1722 :
1723 : // Add locked coins
1724 111495 : if (pwallet->IsLockedCoin(hashTx, i)) {
1725 51 : nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE_ALL);
1726 : }
1727 :
1728 : // Add masternode collaterals which are handled like locked coins
1729 111444 : else if (fMasterNode && tx->vout[i].nValue == collAmt) {
1730 0 : nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
1731 : }
1732 :
1733 265974 : if (!Params().GetConsensus().MoneyRange(nCredit))
1734 0 : throw std::runtime_error("CWalletTx::GetLockedCredit() : value out of range");
1735 : }
1736 :
1737 : return nCredit;
1738 : }
1739 :
1740 0 : CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
1741 : {
1742 0 : if (IsInMainChainImmature()) {
1743 0 : return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
1744 : }
1745 :
1746 : return 0;
1747 : }
1748 :
1749 0 : CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool fUseCache) const
1750 : {
1751 0 : return GetAvailableCredit(fUseCache, ISMINE_WATCH_ONLY);
1752 : }
1753 :
1754 342 : void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
1755 : std::list<COutputEntry>& listSent,
1756 : CAmount& nFee,
1757 : const isminefilter& filter) const
1758 : {
1759 342 : nFee = 0;
1760 342 : listReceived.clear();
1761 342 : listSent.clear();
1762 :
1763 : // Compute fee:
1764 342 : CAmount nDebit = GetDebit(filter);
1765 342 : bool isFromMyTaddr = nDebit > 0; // debit>0 means we signed/sent this transaction
1766 :
1767 342 : if (isFromMyTaddr) {// debit>0 means we signed/sent this transaction
1768 108 : CAmount nValueOut = tx->GetValueOut(); // transasparent outputs plus the negative Sapling valueBalance
1769 108 : CAmount nValueIn = tx->GetShieldedValueIn();
1770 108 : nFee = nDebit - nValueOut + nValueIn;
1771 :
1772 : // If we sent utxos from this transaction, create output for value taken from (negative valueBalance)
1773 : // or added (positive valueBalance) to the transparent value pool by Sapling shielding and unshielding.
1774 108 : if (tx->sapData) {
1775 108 : if (tx->sapData->valueBalance < 0) {
1776 8 : COutputEntry output = {CNoDestination(), -tx->sapData->valueBalance, (int) tx->vout.size()};
1777 4 : listSent.push_back(output);
1778 104 : } else if (tx->sapData->valueBalance > 0) {
1779 0 : COutputEntry output = {CNoDestination(), tx->sapData->valueBalance, (int) tx->vout.size()};
1780 0 : listReceived.push_back(output);
1781 : }
1782 : }
1783 : }
1784 :
1785 : // Sent/received.
1786 342 : bool hasZerocoinSpends = tx->HasZerocoinSpendInputs();
1787 833 : for (unsigned int i = 0; i < tx->vout.size(); ++i) {
1788 491 : const CTxOut& txout = tx->vout[i];
1789 491 : isminetype fIsMine = pwallet->IsMine(txout);
1790 : // Only need to handle txouts if AT LEAST one of these is true:
1791 : // 1) they debit from us (sent)
1792 : // 2) the output is to us (received)
1793 491 : if (nDebit > 0) {
1794 : // Don't report 'change' txouts
1795 215 : if (pwallet->IsChange(txout))
1796 125 : continue;
1797 276 : } else if (!(fIsMine & filter) && !hasZerocoinSpends)
1798 39 : continue;
1799 :
1800 : // In either case, we need to get the destination address
1801 366 : const bool fColdStake = (filter & ISMINE_COLD);
1802 732 : CTxDestination address;
1803 366 : if (txout.IsZerocoinMint()) {
1804 0 : address = CNoDestination();
1805 366 : } else if (!ExtractDestination(txout.scriptPubKey, address, fColdStake)) {
1806 34 : if (!IsCoinStake() && !IsCoinBase()) {
1807 34 : LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", this->GetHash().ToString());
1808 : }
1809 17 : address = CNoDestination();
1810 : }
1811 :
1812 732 : COutputEntry output = {address, txout.nValue, (int)i};
1813 :
1814 : // If we are debited by the transaction, add the output as a "sent" entry
1815 366 : if (nDebit > 0)
1816 129 : listSent.push_back(output);
1817 :
1818 : // If we are receiving the output, add it as a "received" entry
1819 366 : if (fIsMine & filter)
1820 366 : listReceived.push_back(output);
1821 : }
1822 342 : }
1823 :
1824 2 : bool CWallet::Upgrade(std::string& error, const int prevVersion)
1825 : {
1826 6 : LOCK2(cs_wallet, cs_KeyStore);
1827 :
1828 : // Do not upgrade versions if we are already in the last one
1829 2 : if (prevVersion >= FEATURE_SAPLING) {
1830 0 : error = strprintf(_("Cannot upgrade to Sapling wallet (already running Sapling support). Version: %d"), prevVersion);
1831 0 : return false;
1832 : }
1833 :
1834 : // Check if we need to upgrade to HD
1835 2 : if (prevVersion < FEATURE_PRE_SPLIT_KEYPOOL) {
1836 2 : if (!m_spk_man->Upgrade(prevVersion, error)) {
1837 : return false;
1838 : }
1839 : }
1840 :
1841 : // Now upgrade to Sapling manager
1842 2 : if (prevVersion < FEATURE_SAPLING) {
1843 2 : if (!ActivateSaplingWallet()) {
1844 0 : return false;
1845 : }
1846 : }
1847 :
1848 : return true;
1849 : }
1850 :
1851 : /**
1852 : * Scan active chain for relevant transactions after importing keys. This should
1853 : * be called whenever new keys are added to the wallet, with the oldest key
1854 : * creation time.
1855 : *
1856 : * @return Earliest timestamp that could be successfully scanned from. Timestamp
1857 : * returned will be higher than startTime if relevant blocks could not be read.
1858 : */
1859 40 : int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
1860 : {
1861 : // Find starting block. May be null if nCreateTime is greater than the
1862 : // highest blockchain timestamp, in which case there is nothing that needs
1863 : // to be scanned.
1864 40 : CBlockIndex* startBlock = nullptr;
1865 40 : {
1866 40 : LOCK(cs_main);
1867 40 : startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
1868 40 : LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
1869 : }
1870 :
1871 40 : if (startBlock) {
1872 40 : const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, reserver, update);
1873 40 : if (failedBlock) {
1874 0 : return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
1875 : }
1876 : }
1877 : return startTime;
1878 : }
1879 :
1880 : /**
1881 : * Scan the block chain (starting in pindexStart) for transactions
1882 : * from or to us. If fUpdate is true, found transactions that already
1883 : * exist in the wallet will be updated.
1884 : *
1885 : * Returns null if scan was successful. Otherwise, if a complete rescan was not
1886 : * possible (due to pruning or corruption), returns pointer to the most recent
1887 : * block that could not be scanned.
1888 : *
1889 : * If pindexStop is not a nullptr, the scan will stop at the block-index
1890 : * defined by pindexStop
1891 : *
1892 : * Caller needs to make sure pindexStop (and the optional pindexStart) are on
1893 : * the main chain after to the addition of any new keys you want to detect
1894 : * transactions for.
1895 : */
1896 1179 : CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate, bool fromStartup)
1897 : {
1898 1179 : int64_t nNow = GetTime();
1899 :
1900 1179 : assert(reserver.isReserved());
1901 1179 : if (pindexStop) {
1902 1 : assert(pindexStop->nHeight >= pindexStart->nHeight);
1903 : }
1904 :
1905 1179 : CBlockIndex* pindex = pindexStart;
1906 1179 : CBlockIndex* ret = nullptr;
1907 1179 : {
1908 1179 : ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
1909 1179 : CBlockIndex* tip = nullptr;
1910 1179 : double dProgressStart;
1911 1179 : double dProgressTip;
1912 1179 : {
1913 1179 : LOCK(cs_main);
1914 1179 : tip = chainActive.Tip();
1915 1179 : dProgressStart = Checkpoints::GuessVerificationProgress(pindex, false);
1916 1179 : dProgressTip = Checkpoints::GuessVerificationProgress(tip, false);
1917 : }
1918 :
1919 1179 : std::vector<uint256> myTxHashes;
1920 28318 : while (pindex && !fAbortRescan) {
1921 27140 : double gvp = 0;
1922 27140 : if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) {
1923 867 : gvp = WITH_LOCK(cs_main, return Checkpoints::GuessVerificationProgress(pindex, false); );
1924 954 : ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
1925 : }
1926 27140 : if (GetTime() >= nNow + 60) {
1927 0 : nNow = GetTime();
1928 0 : LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, gvp);
1929 : }
1930 27140 : if (fromStartup && ShutdownRequested()) {
1931 : break;
1932 : }
1933 :
1934 27140 : CBlock block;
1935 27140 : if (ReadBlockFromDisk(block, pindex)) {
1936 81420 : LOCK2(cs_main, cs_wallet);
1937 54280 : if (pindex && !chainActive.Contains(pindex)) {
1938 : // Abort scan if current block is no longer active, to prevent
1939 : // marking transactions as coming from the wrong block.
1940 0 : ret = pindex;
1941 0 : break;
1942 : }
1943 115698 : for (int posInBlock = 0; posInBlock < (int) block.vtx.size(); posInBlock++) {
1944 88558 : const auto& tx = block.vtx[posInBlock];
1945 88558 : CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, pindex->nHeight, pindex->GetBlockHash(), posInBlock);
1946 88558 : if (AddToWalletIfInvolvingMe(tx, confirm, fUpdate)) {
1947 8687 : myTxHashes.push_back(tx->GetHash());
1948 : }
1949 : }
1950 :
1951 : // Sapling
1952 : // This should never fail: we should always be able to get the tree
1953 : // state on the path to the tip of our chain
1954 27140 : if (pindex->pprev) {
1955 26105 : if (Params().GetConsensus().NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_V5_0)) {
1956 3508 : SaplingMerkleTree saplingTree;
1957 1754 : assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree));
1958 : // Increment note witness caches
1959 3508 : ChainTipAdded(pindex, &block, saplingTree);
1960 : }
1961 : }
1962 : } else {
1963 0 : ret = pindex;
1964 : }
1965 27140 : if (pindex == pindexStop) {
1966 : break;
1967 : }
1968 27139 : {
1969 54278 : LOCK(cs_main);
1970 27139 : pindex = chainActive.Next(pindex);
1971 54278 : if (tip != chainActive.Tip()) {
1972 0 : tip = chainActive.Tip();
1973 : // in case the tip has changed, update progress max
1974 0 : dProgressTip = Checkpoints::GuessVerificationProgress(tip, false);
1975 : }
1976 : }
1977 : }
1978 :
1979 : // Sapling
1980 : // After rescanning, persist Sapling note data that might have changed, e.g. nullifiers.
1981 : // Do not flush the wallet here for performance reasons.
1982 2358 : WalletBatch batch(*database, "r+", false);
1983 9866 : for (const auto& hash : myTxHashes) {
1984 8687 : CWalletTx& wtx = mapWallet.at(hash);
1985 8687 : if (!wtx.mapSaplingNoteData.empty()) {
1986 77 : if (!batch.WriteTx(wtx)) {
1987 0 : LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString());
1988 : }
1989 : }
1990 : }
1991 :
1992 1179 : if (pindex && fAbortRescan) {
1993 0 : LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex, false));
1994 : }
1995 2358 : ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
1996 : }
1997 1179 : return ret;
1998 : }
1999 :
2000 387 : void CWallet::ReacceptWalletTransactions(bool fFirstLoad)
2001 : {
2002 774 : LOCK2(cs_main, cs_wallet);
2003 774 : std::map<int64_t, CWalletTx*> mapSorted;
2004 :
2005 : // Sort pending wallet transactions based on their initial wallet insertion order
2006 9114 : for (std::pair<const uint256, CWalletTx>& item: mapWallet) {
2007 8727 : const uint256& wtxid = item.first;
2008 8727 : CWalletTx& wtx = item.second;
2009 8727 : assert(wtx.GetHash() == wtxid);
2010 :
2011 8727 : int nDepth = wtx.GetDepthInMainChain();
2012 9352 : if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && nDepth == 0 && !wtx.isAbandoned()) {
2013 38 : mapSorted.emplace(wtx.nOrderPos, &wtx);
2014 : }
2015 : }
2016 :
2017 : // Try to add wallet transactions to memory pool
2018 425 : for (std::pair<const int64_t, CWalletTx*>& item: mapSorted) {
2019 38 : CWalletTx& wtx = *(item.second);
2020 :
2021 76 : CValidationState state;
2022 38 : bool fSuccess = wtx.AcceptToMemoryPool(state);
2023 38 : if (!fSuccess && fFirstLoad && GetTime() - wtx.GetTxTime() > 12*60*60) {
2024 : //First load of wallet, failed to accept to mempool, and older than 12 hours... not likely to ever
2025 : //make it in to mempool
2026 0 : AbandonTransaction(wtx.GetHash());
2027 : }
2028 : }
2029 387 : }
2030 :
2031 3410575 : bool CWalletTx::InMempool() const
2032 : {
2033 3410575 : return fInMempool;
2034 : }
2035 :
2036 23838 : void CWalletTx::RelayWalletTransaction(CConnman* connman)
2037 : {
2038 51933 : if (!connman || IsCoinBase() || IsCoinStake()) {
2039 : // Nothing to do. Return early
2040 21782 : return;
2041 : }
2042 2056 : if (GetDepthInMainChain() == 0 && !isAbandoned()) {
2043 1426 : const uint256& hash = GetHash();
2044 1426 : LogPrintf("Relaying wtx %s\n", hash.ToString());
2045 1426 : CInv inv(MSG_TX, hash);
2046 1426 : connman->ForEachNode([&inv](CNode* pnode) {
2047 2229 : pnode->PushInventory(inv);
2048 2229 : });
2049 : }
2050 : }
2051 :
2052 393 : std::set<uint256> CWalletTx::GetConflicts() const
2053 : {
2054 393 : std::set<uint256> result;
2055 393 : if (pwallet != nullptr) {
2056 393 : uint256 myHash = GetHash();
2057 786 : result = pwallet->GetConflicts(myHash);
2058 393 : result.erase(myHash);
2059 : }
2060 393 : return result;
2061 : }
2062 :
2063 726 : void CWallet::Flush(bool shutdown)
2064 : {
2065 726 : database->Flush(shutdown);
2066 726 : }
2067 :
2068 1789460 : void CWallet::ResendWalletTransactions(CConnman* connman)
2069 : {
2070 : // Do this infrequently and randomly to avoid giving away
2071 : // that these are our transactions.
2072 1789460 : if (GetTime() < nNextResend) {
2073 : return;
2074 : }
2075 816 : bool fFirst = (nNextResend == 0);
2076 816 : nNextResend = GetTime() + GetRand(30 * 60);
2077 816 : if (fFirst) {
2078 : return;
2079 : }
2080 :
2081 : // Only do it if there's been a new block since last time
2082 598 : if (nTimeBestReceived < nLastResend) {
2083 : return;
2084 : }
2085 570 : nLastResend = GetTime();
2086 :
2087 : // Rebroadcast any of our txes that aren't in a block yet
2088 570 : LogPrintf("ResendWalletTransactions()\n");
2089 570 : {
2090 1140 : LOCK(cs_wallet);
2091 : // Sort them in chronological order
2092 1140 : std::multimap<unsigned int, CWalletTx*> mapSorted;
2093 24619 : for (std::pair<const uint256, CWalletTx> & item : mapWallet) {
2094 24049 : CWalletTx& wtx = item.second;
2095 : // Don't rebroadcast until it's had plenty of time that
2096 : // it should have gotten in already by now.
2097 24049 : if (nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60) {
2098 22401 : mapSorted.emplace(wtx.nTimeReceived, &wtx);
2099 : }
2100 : }
2101 22971 : for (std::pair<const unsigned int, CWalletTx*> & item : mapSorted) {
2102 22401 : CWalletTx& wtx = *item.second;
2103 22401 : wtx.RelayWalletTransaction(connman);
2104 : }
2105 : }
2106 : }
2107 :
2108 40278 : void CWallet::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
2109 : {
2110 40278 : nTimeBestReceived = GetTime();
2111 40278 : }
2112 :
2113 : /** @} */ // end of mapWallet
2114 :
2115 :
2116 : /** @defgroup Actions
2117 : *
2118 : * @{
2119 : */
2120 :
2121 0 : CWallet::Balance CWallet::GetBalance(const int min_depth) const
2122 : {
2123 0 : Balance ret;
2124 0 : {
2125 0 : LOCK(cs_wallet);
2126 0 : std::set<uint256> trusted_parents;
2127 0 : for (const auto& entry : mapWallet) {
2128 0 : const CWalletTx& wtx = entry.second;
2129 0 : const bool is_trusted{wtx.IsTrusted()};
2130 0 : const int tx_depth{wtx.GetDepthInMainChain()};
2131 0 : const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE_TRANSPARENT)};
2132 0 : const CAmount tx_credit_shield_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE_SHIELDED)};
2133 0 : if (is_trusted && tx_depth >= min_depth) {
2134 0 : ret.m_mine_trusted += tx_credit_mine;
2135 0 : ret.m_mine_trusted_shield += tx_credit_shield_mine;
2136 0 : if (wtx.tx->HasP2CSOutputs()) {
2137 0 : ret.m_mine_cs_delegated_trusted += wtx.GetStakeDelegationCredit();
2138 : }
2139 : }
2140 0 : if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
2141 0 : ret.m_mine_untrusted_pending += tx_credit_mine;
2142 0 : ret.m_mine_untrusted_shielded_balance += tx_credit_shield_mine;
2143 : }
2144 0 : ret.m_mine_immature += wtx.GetImmatureCredit();
2145 : }
2146 : }
2147 0 : return ret;
2148 : }
2149 :
2150 1525 : CAmount CWallet::loopTxsBalance(const std::function<void(const uint256&, const CWalletTx&, CAmount&)>& method) const
2151 : {
2152 1525 : CAmount nTotal = 0;
2153 1525 : {
2154 1525 : LOCK(cs_wallet);
2155 226613 : for (const auto& it : mapWallet) {
2156 225088 : method(it.first, it.second, nTotal);
2157 : }
2158 : }
2159 1525 : return nTotal;
2160 : }
2161 :
2162 406 : CAmount CWallet::GetAvailableBalance(bool fIncludeDelegated, bool fIncludeShielded) const
2163 : {
2164 406 : isminefilter filter;
2165 406 : if (fIncludeDelegated && fIncludeShielded) {
2166 406 : filter = ISMINE_SPENDABLE_ALL;
2167 0 : } else if (fIncludeDelegated) {
2168 0 : filter = ISMINE_SPENDABLE_TRANSPARENT;
2169 0 : } else if (fIncludeShielded) {
2170 0 : filter = ISMINE_SPENDABLE_NO_DELEGATED;
2171 : } else {
2172 0 : filter = ISMINE_SPENDABLE;
2173 : }
2174 406 : return GetAvailableBalance(filter, true, 0);
2175 : }
2176 :
2177 544 : CAmount CWallet::GetAvailableBalance(isminefilter& filter, bool useCache, int minDepth) const
2178 : {
2179 544 : return loopTxsBalance([filter, useCache, minDepth](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal){
2180 46928 : bool fConflicted;
2181 46928 : int depth;
2182 46928 : if (pcoin.IsTrusted(depth, fConflicted) && depth >= minDepth) {
2183 46853 : nTotal += pcoin.GetAvailableCredit(useCache, filter);
2184 : }
2185 544 : });
2186 : }
2187 :
2188 75 : CAmount CWallet::GetColdStakingBalance() const
2189 : {
2190 75 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2191 5126 : if (pcoin.tx->HasP2CSOutputs() && pcoin.IsTrusted())
2192 412 : nTotal += pcoin.GetColdStakingCredit();
2193 75 : });
2194 : }
2195 :
2196 561 : CAmount CWallet::GetStakingBalance(const bool fIncludeColdStaking) const
2197 : {
2198 561 : return std::max(CAmount(0), loopTxsBalance(
2199 287848 : [fIncludeColdStaking](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2200 148968 : if (pcoin.IsTrusted() && pcoin.GetDepthInMainChain() >= Params().GetConsensus().nStakeMinDepth) {
2201 138880 : nTotal += pcoin.GetAvailableCredit(); // available coins
2202 138880 : nTotal -= pcoin.GetStakeDelegationCredit(); // minus delegated coins, if any
2203 138880 : nTotal -= pcoin.GetLockedCredit(); // minus locked coins, if any
2204 138880 : if (fIncludeColdStaking)
2205 138880 : nTotal += pcoin.GetColdStakingCredit(); // plus cold coins, if any and if requested
2206 : }
2207 1122 : }));
2208 : }
2209 :
2210 74 : CAmount CWallet::GetDelegatedBalance() const
2211 : {
2212 74 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2213 5122 : if (pcoin.tx->HasP2CSOutputs() && pcoin.IsTrusted())
2214 422 : nTotal += pcoin.GetStakeDelegationCredit();
2215 74 : });
2216 : }
2217 :
2218 0 : CAmount CWallet::GetLockedCoins() const
2219 : {
2220 0 : LOCK(cs_wallet);
2221 0 : if (setLockedCoins.empty()) return 0;
2222 :
2223 0 : CAmount ret = 0;
2224 0 : for (const auto& coin : setLockedCoins) {
2225 0 : auto it = mapWallet.find(coin.hash);
2226 0 : if (it != mapWallet.end()) {
2227 0 : const CWalletTx& pcoin = it->second;
2228 0 : if (pcoin.IsTrusted() && pcoin.GetDepthInMainChain() > 0) {
2229 0 : ret += it->second.tx->vout.at(coin.n).nValue;
2230 : }
2231 : }
2232 : }
2233 0 : return ret;
2234 : }
2235 :
2236 0 : CAmount CWallet::GetLockedShieldCoins() const
2237 : {
2238 0 : LOCK(cs_wallet);
2239 0 : if (setLockedNotes.empty()) return 0;
2240 :
2241 0 : CAmount ret = 0;
2242 0 : for (const auto& op : setLockedNotes) {
2243 0 : auto it = mapWallet.find(op.hash);
2244 0 : if (it != mapWallet.end()) {
2245 0 : const CWalletTx& pcoin = it->second;
2246 0 : if (pcoin.IsTrusted() && pcoin.GetDepthInMainChain() > 0) {
2247 0 : Optional<CAmount> val = pcoin.mapSaplingNoteData.at(op).amount;
2248 0 : if (val) {
2249 0 : ret += *val;
2250 : }
2251 : }
2252 : }
2253 : }
2254 0 : return ret;
2255 : }
2256 :
2257 :
2258 71 : CAmount CWallet::GetUnconfirmedBalance(isminetype filter) const
2259 : {
2260 71 : return loopTxsBalance([filter](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2261 4882 : if (!pcoin.IsTrusted() && pcoin.GetDepthInMainChain() == 0 && pcoin.InMempool())
2262 3 : nTotal += pcoin.GetCredit(filter);
2263 71 : });
2264 : }
2265 :
2266 68 : CAmount CWallet::GetImmatureBalance() const
2267 : {
2268 68 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2269 4762 : nTotal += pcoin.GetImmatureCredit(false);
2270 68 : });
2271 : }
2272 :
2273 66 : CAmount CWallet::GetImmatureColdStakingBalance() const
2274 : {
2275 66 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2276 4650 : nTotal += pcoin.GetImmatureCredit(false, ISMINE_COLD);
2277 66 : });
2278 : }
2279 :
2280 66 : CAmount CWallet::GetImmatureDelegatedBalance() const
2281 : {
2282 66 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2283 4650 : nTotal += pcoin.GetImmatureCredit(false, ISMINE_SPENDABLE_DELEGATED);
2284 66 : });
2285 : }
2286 :
2287 0 : CAmount CWallet::GetWatchOnlyBalance() const
2288 : {
2289 0 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2290 0 : if (pcoin.IsTrusted())
2291 0 : nTotal += pcoin.GetAvailableWatchOnlyCredit();
2292 0 : });
2293 : }
2294 :
2295 0 : CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
2296 : {
2297 0 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2298 0 : if (!pcoin.IsTrusted() && pcoin.GetDepthInMainChain() == 0 && pcoin.InMempool())
2299 0 : nTotal += pcoin.GetAvailableWatchOnlyCredit();
2300 0 : });
2301 : }
2302 :
2303 0 : CAmount CWallet::GetImmatureWatchOnlyBalance() const
2304 : {
2305 0 : return loopTxsBalance([](const uint256& id, const CWalletTx& pcoin, CAmount& nTotal) {
2306 0 : nTotal += pcoin.GetImmatureWatchOnlyCredit();
2307 0 : });
2308 : }
2309 :
2310 : // Calculate total balance in a different way from GetBalance. The biggest
2311 : // difference is that GetBalance sums up all unspent TxOuts paying to the
2312 : // wallet, while this sums up both spent and unspent TxOuts paying to the
2313 : // wallet, and then subtracts the values of TxIns spending from the wallet. This
2314 : // also has fewer restrictions on which unconfirmed transactions are considered
2315 : // trusted.
2316 6 : CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth) const
2317 : {
2318 6 : LOCK(cs_wallet);
2319 :
2320 6 : CAmount balance = 0;
2321 378 : for (const auto& entry : mapWallet) {
2322 372 : const CWalletTx& wtx = entry.second;
2323 372 : bool fConflicted;
2324 372 : const int depth = wtx.GetDepthAndMempool(fConflicted);
2325 372 : if (!IsFinalTx(wtx.tx, m_last_block_processed_height) || wtx.GetBlocksToMaturity() > 0 || depth < 0 || fConflicted) {
2326 252 : continue;
2327 : }
2328 :
2329 : // Loop through tx outputs and add incoming payments. For outgoing txs,
2330 : // treat change outputs specially, as part of the amount debited.
2331 120 : CAmount debit = wtx.GetDebit(filter);
2332 120 : const bool outgoing = debit > 0;
2333 288 : for (const CTxOut& out : wtx.tx->vout) {
2334 168 : if (outgoing && IsChange(out)) {
2335 12 : debit -= out.nValue;
2336 156 : } else if (IsMine(out) & filter && depth >= minDepth) {
2337 115 : balance += out.nValue;
2338 : }
2339 : }
2340 :
2341 : // For outgoing txs, subtract amount debited.
2342 120 : if (outgoing) {
2343 12 : balance -= debit;
2344 : }
2345 : }
2346 :
2347 12 : return balance;
2348 : }
2349 :
2350 : // Sapling
2351 1 : CAmount CWallet::GetAvailableShieldedBalance(bool fUseCache) const
2352 : {
2353 1 : isminefilter filter = ISMINE_SPENDABLE_SHIELDED;
2354 1 : return GetAvailableBalance(filter, fUseCache);
2355 : };
2356 :
2357 1 : CAmount CWallet::GetUnconfirmedShieldedBalance() const
2358 : {
2359 1 : return GetUnconfirmedBalance(ISMINE_SPENDABLE_SHIELDED);
2360 : };
2361 :
2362 0 : void CWallet::GetAvailableP2CSCoins(std::vector<COutput>& vCoins) const {
2363 0 : vCoins.clear();
2364 0 : {
2365 0 : LOCK(cs_wallet);
2366 0 : for (const auto& it : mapWallet) {
2367 0 : const uint256& wtxid = it.first;
2368 0 : const CWalletTx* pcoin = &it.second;
2369 :
2370 0 : bool fConflicted;
2371 0 : int nDepth = pcoin->GetDepthAndMempool(fConflicted);
2372 :
2373 0 : if (fConflicted || nDepth < 0)
2374 0 : continue;
2375 :
2376 0 : bool fSafe = pcoin->IsTrusted();
2377 :
2378 0 : if (pcoin->tx->HasP2CSOutputs()) {
2379 0 : for (int i = 0; i < (int) pcoin->tx->vout.size(); i++) {
2380 0 : const auto &utxo = pcoin->tx->vout[i];
2381 :
2382 0 : if (IsSpent(wtxid, i))
2383 0 : continue;
2384 :
2385 0 : if (utxo.scriptPubKey.IsPayToColdStaking()) {
2386 0 : isminetype mine = IsMine(utxo);
2387 0 : bool isMineSpendable = mine & ISMINE_SPENDABLE_DELEGATED;
2388 0 : if (mine & ISMINE_COLD || isMineSpendable)
2389 : // Depth and solvability members are not used, no need waste resources and set them for now.
2390 0 : vCoins.emplace_back(pcoin, i, 0, isMineSpendable, true, fSafe);
2391 : }
2392 : }
2393 : }
2394 : }
2395 : }
2396 :
2397 0 : }
2398 :
2399 : /**
2400 : * Test if the transaction is spendable.
2401 : */
2402 4337965 : static bool CheckTXAvailabilityInternal(const CWalletTx* pcoin, bool fOnlySafe, int& nDepth, bool& safeTx)
2403 : {
2404 4337965 : safeTx = pcoin->IsTrusted();
2405 4337965 : if (fOnlySafe && !safeTx) return false;
2406 4337826 : if (pcoin->GetBlocksToMaturity() > 0) return false;
2407 :
2408 4067476 : nDepth = pcoin->GetDepthInMainChain();
2409 :
2410 : // We should not consider coins which aren't at least in our mempool
2411 : // It's possible for these to be conflicted via ancestors which we may never be able to detect
2412 4067476 : if (nDepth == 0 && !pcoin->InMempool()) return false;
2413 :
2414 : return true;
2415 : }
2416 :
2417 : // cs_main lock required
2418 983733 : static bool CheckTXAvailability(const CWalletTx* pcoin, bool fOnlySafe, int& nDepth, bool& safeTx)
2419 : {
2420 983733 : AssertLockHeld(cs_main);
2421 983733 : if (!CheckFinalTx(pcoin->tx)) return false;
2422 983733 : return CheckTXAvailabilityInternal(pcoin, fOnlySafe, nDepth, safeTx);
2423 : }
2424 :
2425 : // cs_main lock NOT required
2426 3354232 : static bool CheckTXAvailability(const CWalletTx* pcoin,
2427 : bool fOnlySafe,
2428 : int& nDepth,
2429 : bool& safeTx,
2430 : int nBlockHeight)
2431 : {
2432 : // Mimic CheckFinalTx without cs_main lock
2433 3354232 : if (!IsFinalTx(pcoin->tx, nBlockHeight + 1, GetAdjustedTime())) return false;
2434 3354232 : return CheckTXAvailabilityInternal(pcoin, fOnlySafe, nDepth, safeTx);
2435 : }
2436 :
2437 14 : bool CWallet::GetMasternodeVinAndKeys(CPubKey& pubKeyRet,
2438 : CKey& keyRet,
2439 : const COutPoint& collateralOut,
2440 : bool fValidateCollateral,
2441 : std::string& strError)
2442 : {
2443 : // wait for reindex and/or import to finish
2444 14 : if (fImporting || fReindex) return false;
2445 :
2446 : // Find specific vin
2447 14 : const CWalletTx* wtx = GetWalletTx(collateralOut.hash);
2448 14 : if (!wtx) {
2449 0 : strError = "collateral tx not found in the wallet";
2450 0 : return error("%s: %s", __func__, strError);
2451 : }
2452 :
2453 : // Verify index limits
2454 14 : if (collateralOut.n < 0 || collateralOut.n >= (uint32_t) wtx->tx->vout.size()) {
2455 0 : strError = "Invalid masternode output index";
2456 0 : return error("%s: output index %d not found in %s", __func__, collateralOut.n, collateralOut.hash.GetHex());
2457 : }
2458 :
2459 28 : CTxOut txOut = wtx->tx->vout[collateralOut.n];
2460 :
2461 : // Masternode collateral value
2462 14 : const auto& consensus = Params().GetConsensus();
2463 14 : if (txOut.nValue != consensus.nMNCollateralAmt) {
2464 0 : strError = strprintf("Invalid collateral tx value, must be %s PIV", FormatMoney(Params().GetConsensus().nMNCollateralAmt));
2465 0 : return error("%s: tx %s, index %d not a masternode collateral", __func__, collateralOut.hash.GetHex(), collateralOut.n);
2466 : }
2467 :
2468 14 : if (fValidateCollateral) {
2469 14 : int nDepth = 0;
2470 14 : {
2471 14 : LOCK(cs_wallet);
2472 : // Check availability
2473 14 : bool safeTx = false;
2474 14 : if (!CheckTXAvailability(wtx, true, nDepth, safeTx, m_last_block_processed_height)) {
2475 0 : strError = "Not available collateral transaction";
2476 0 : return error("%s: tx %s not available", __func__, collateralOut.hash.GetHex());
2477 : }
2478 :
2479 : // Skip spent coins
2480 14 : if (IsSpent(collateralOut.hash, collateralOut.n)) {
2481 0 : strError = "Error: collateral already spent";
2482 0 : return error("%s: tx %s already spent", __func__, collateralOut.hash.GetHex());
2483 : }
2484 : }
2485 :
2486 : // Depth must be at least MASTERNODE_MIN_CONFIRMATIONS
2487 14 : if (nDepth < consensus.MasternodeCollateralMinConf()) {
2488 0 : strError = strprintf("Collateral tx must have at least %d confirmations, has %d",
2489 0 : consensus.MasternodeCollateralMinConf(), nDepth);
2490 0 : return error("%s: %s", __func__, strError);
2491 : }
2492 : }
2493 :
2494 28 : CTxDestination destCollateral;
2495 14 : ExtractDestination(txOut.scriptPubKey, destCollateral, false);
2496 14 : const CKeyID* keyID = boost::get<CKeyID>(&destCollateral);
2497 14 : if (!keyID) {
2498 0 : LogPrintf("%s: Address does not refer to a key\n", __func__);
2499 : return false;
2500 : }
2501 :
2502 14 : if (!GetKey(*keyID, keyRet)) {
2503 0 : LogPrintf("%s: Private key for address is not known\n", __func__);
2504 : return false;
2505 : }
2506 :
2507 14 : pubKeyRet = keyRet.GetPubKey();
2508 : return true;
2509 : }
2510 :
2511 9215932 : CWallet::OutputAvailabilityResult CWallet::CheckOutputAvailability(
2512 : const CTxOut& output,
2513 : const unsigned int outIndex,
2514 : const uint256& wtxid,
2515 : const CCoinControl* coinControl,
2516 : const bool fCoinsSelected,
2517 : const bool fIncludeColdStaking,
2518 : const bool fIncludeDelegated,
2519 : const bool fIncludeLocked) const
2520 : {
2521 9215932 : OutputAvailabilityResult res;
2522 :
2523 : // Check if the utxo was spent.
2524 9215932 : if (IsSpent(wtxid, outIndex)) return res;
2525 :
2526 3616248 : isminetype mine = IsMine(output);
2527 :
2528 : // Check If not mine
2529 3616248 : if (mine == ISMINE_NO) return res;
2530 :
2531 : // Skip locked utxo
2532 3319028 : if (!fIncludeLocked && IsLockedCoin(wtxid, outIndex)) return res;
2533 :
2534 : // Check if we should include zero value utxo
2535 3318408 : if (output.nValue <= 0) return res;
2536 3318408 : if (fCoinsSelected && coinControl && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(wtxid, outIndex)))
2537 0 : return res;
2538 :
2539 : // --Skip P2CS outputs
2540 : // skip cold coins
2541 3318408 : if (mine == ISMINE_COLD && (!fIncludeColdStaking || !HasDelegator(output))) return res;
2542 : // skip delegated coins
2543 3318388 : if (mine == ISMINE_SPENDABLE_DELEGATED && !fIncludeDelegated) return res;
2544 :
2545 3318188 : res.solvable = IsSolvable(*this, output.scriptPubKey, mine == ISMINE_COLD);
2546 :
2547 6636966 : res.spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
2548 3318188 : (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && res.solvable)) ||
2549 1176 : ((mine & ((fIncludeColdStaking ? ISMINE_COLD : ISMINE_NO) |
2550 588 : (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO);
2551 3318188 : res.available = true;
2552 3318188 : return res;
2553 : }
2554 :
2555 2731 : bool CWallet::AvailableCoins(std::vector<COutput>* pCoins, // --> populates when != nullptr
2556 : const CCoinControl* coinControl, // Default: nullptr
2557 : AvailableCoinsFilter coinsFilter) const
2558 : {
2559 2731 : if (pCoins) pCoins->clear();
2560 2731 : const bool fCoinsSelected = (coinControl != nullptr) && coinControl->HasSelected();
2561 : // include delegated coins when coinControl is active
2562 2731 : if (!coinsFilter.fIncludeDelegated && fCoinsSelected)
2563 8 : coinsFilter.fIncludeDelegated = true;
2564 :
2565 2731 : {
2566 5462 : LOCK(cs_wallet);
2567 2731 : CAmount nTotal = 0;
2568 3356945 : for (const auto& entry : mapWallet) {
2569 3354222 : const uint256& wtxid = entry.first;
2570 3354222 : const CWalletTx* pcoin = &entry.second;
2571 :
2572 : // Check if the tx is selectable
2573 3354222 : int nDepth = 0;
2574 3354222 : bool safeTx = false;
2575 3354222 : if (!CheckTXAvailability(pcoin, coinsFilter.fOnlySafe, nDepth, safeTx, m_last_block_processed_height))
2576 1152807 : continue;
2577 :
2578 : // Check min depth filtering requirements
2579 3200565 : if (nDepth < coinsFilter.minDepth) continue;
2580 :
2581 10370210 : for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
2582 8168845 : const auto& output = pcoin->tx->vout[i];
2583 :
2584 : // Filter by value if needed
2585 8168845 : if (coinsFilter.nMaxOutValue > 0 && output.nValue > coinsFilter.nMaxOutValue) {
2586 5179500 : continue;
2587 : }
2588 8168785 : if (coinsFilter.nMinOutValue > 0 && output.nValue < coinsFilter.nMinOutValue) {
2589 41 : continue;
2590 : }
2591 :
2592 : // Filter by specific destinations if needed
2593 8168745 : if (coinsFilter.onlyFilteredDest && !coinsFilter.onlyFilteredDest->empty()) {
2594 783 : CTxDestination address;
2595 1362 : if (!ExtractDestination(output.scriptPubKey, address) || !coinsFilter.onlyFilteredDest->count(address)) {
2596 579 : continue;
2597 : }
2598 : }
2599 :
2600 : // Now check for chain availability
2601 8168165 : auto res = CheckOutputAvailability(
2602 : output,
2603 : i,
2604 : wtxid,
2605 : coinControl,
2606 : fCoinsSelected,
2607 8168165 : coinsFilter.fIncludeColdStaking,
2608 8168165 : coinsFilter.fIncludeDelegated,
2609 8168165 : coinsFilter.fIncludeLocked);
2610 :
2611 8168165 : if (!res.available) continue;
2612 2989355 : if (coinsFilter.fOnlySpendable && !res.spendable) continue;
2613 :
2614 : // found valid coin
2615 2989355 : if (!pCoins) return true;
2616 2989355 : pCoins->emplace_back(pcoin, (int) i, nDepth, res.spendable, res.solvable, safeTx);
2617 :
2618 : // Checks the sum amount of all UTXO's.
2619 2989355 : if (coinsFilter.nMinimumSumAmount != 0) {
2620 17 : nTotal += output.nValue;
2621 :
2622 17 : if (nTotal >= coinsFilter.nMinimumSumAmount) {
2623 : return true;
2624 : }
2625 : }
2626 :
2627 : // Checks the maximum number of UTXO's.
2628 2989345 : if (coinsFilter.nMaximumCount > 0 && pCoins->size() >= coinsFilter.nMaximumCount) {
2629 : return true;
2630 : }
2631 : }
2632 : }
2633 2726 : return (pCoins && !pCoins->empty());
2634 : }
2635 : }
2636 :
2637 1 : std::map<CTxDestination , std::vector<COutput> > CWallet::AvailableCoinsByAddress(bool fOnlySafe, CAmount maxCoinValue, bool fIncludeColdStaking)
2638 : {
2639 1 : CWallet::AvailableCoinsFilter coinFilter;
2640 1 : coinFilter.fIncludeColdStaking = true;
2641 1 : coinFilter.fOnlySafe = fOnlySafe;
2642 1 : coinFilter.fIncludeColdStaking = fIncludeColdStaking;
2643 1 : coinFilter.nMaxOutValue = maxCoinValue;
2644 1 : std::vector<COutput> vCoins;
2645 1 : AvailableCoins(&vCoins, nullptr, coinFilter);
2646 :
2647 1 : std::map<CTxDestination, std::vector<COutput> > mapCoins;
2648 11 : for (const COutput& out : vCoins) {
2649 20 : CTxDestination address;
2650 10 : bool fColdStakeAddr = false;
2651 10 : if (!ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address, fColdStakeAddr)) {
2652 0 : bool isP2CS = out.tx->tx->vout[out.i].scriptPubKey.IsPayToColdStaking();
2653 0 : if (isP2CS && !fIncludeColdStaking) {
2654 : // It must never happen as the coin filtering process shouldn't had added the P2CS in the first place
2655 0 : assert(false);
2656 : }
2657 : // if this is a P2CS we don't have the owner key - check if we have the staking key
2658 0 : fColdStakeAddr = true;
2659 0 : if (!isP2CS || !ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address, fColdStakeAddr) )
2660 0 : continue;
2661 : }
2662 :
2663 10 : mapCoins[address].emplace_back(out);
2664 : }
2665 :
2666 2 : return mapCoins;
2667 : }
2668 :
2669 2934 : static void ApproximateBestSubset(const std::vector<std::pair<CAmount, std::pair<const CWalletTx*,unsigned int> > >& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,
2670 : std::vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
2671 : {
2672 2934 : std::vector<char> vfIncluded;
2673 :
2674 2934 : vfBest.assign(vValue.size(), true);
2675 2934 : nBest = nTotalLower;
2676 :
2677 2934 : FastRandomContext insecure_rand;
2678 :
2679 1835059 : for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++) {
2680 1832125 : vfIncluded.assign(vValue.size(), false);
2681 1832125 : CAmount nTotal = 0;
2682 1832125 : bool fReachedTarget = false;
2683 4610395 : for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++) {
2684 349975270 : for (unsigned int i = 0; i < vValue.size(); i++) {
2685 : //The solver here uses a randomized algorithm,
2686 : //the randomness serves no real security purpose but is just
2687 : //needed to prevent degenerate behavior and it is important
2688 : //that the rng is fast. We do not use a constant random sequence,
2689 : //because there may be some privacy improvement by making
2690 : //the selection random.
2691 690506320 : if (nPass == 0 ? insecure_rand.randbool() : !vfIncluded[i]) {
2692 173969615 : nTotal += vValue[i].first;
2693 173969615 : vfIncluded[i] = true;
2694 173969615 : if (nTotal >= nTargetValue) {
2695 163518819 : fReachedTarget = true;
2696 163518819 : if (nTotal < nBest) {
2697 4515 : nBest = nTotal;
2698 4515 : vfBest = vfIncluded;
2699 : }
2700 163518819 : nTotal -= vValue[i].first;
2701 163518819 : vfIncluded[i] = false;
2702 : }
2703 : }
2704 : }
2705 : }
2706 : }
2707 2934 : }
2708 :
2709 2486 : bool CWallet::StakeableCoins(std::vector<CStakeableOutput>* pCoins)
2710 : {
2711 4955 : const bool fIncludeColdStaking = !sporkManager.IsSporkActive(SPORK_19_COLDSTAKING_MAINTENANCE) &&
2712 7424 : gArgs.GetBoolArg("-coldstaking", DEFAULT_COLDSTAKING);
2713 :
2714 2486 : if (pCoins) pCoins->clear();
2715 :
2716 7458 : LOCK2(cs_main, cs_wallet);
2717 986219 : for (const auto& it : mapWallet) {
2718 983733 : const uint256& wtxid = it.first;
2719 983733 : const CWalletTx* pcoin = &(it).second;
2720 :
2721 : // Check if the tx is selectable
2722 983733 : int nDepth = 0;
2723 983733 : bool safeTx = false;
2724 983733 : if (!CheckTXAvailability(pcoin, true, nDepth, safeTx))
2725 231013 : continue;
2726 :
2727 : // Check min depth requirement for stake inputs
2728 754566 : if (nDepth < Params().GetConsensus().nStakeMinDepth) continue;
2729 :
2730 752720 : const CBlockIndex* pindex = nullptr;
2731 1800484 : for (unsigned int index = 0; index < pcoin->tx->vout.size(); index++) {
2732 :
2733 1047767 : auto res = CheckOutputAvailability(
2734 1047767 : pcoin->tx->vout[index],
2735 : index,
2736 : wtxid,
2737 : nullptr, // coin control
2738 : false, // fIncludeDelegated
2739 : fIncludeColdStaking,
2740 : false,
2741 1047767 : false); // fIncludeLocked
2742 :
2743 1047767 : if (!res.available || !res.spendable) continue;
2744 :
2745 : // found valid coin
2746 328438 : if (!pCoins) return true;
2747 328438 : if (!pindex) pindex = mapBlockIndex.at(pcoin->m_confirm.hashBlock);
2748 328438 : pCoins->emplace_back(pcoin, (int) index, nDepth, pindex);
2749 : }
2750 : }
2751 2486 : return (pCoins && !pCoins->empty());
2752 : }
2753 :
2754 6921 : bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet) const
2755 : {
2756 6921 : setCoinsRet.clear();
2757 6921 : nValueRet = 0;
2758 :
2759 : // List of values less than target
2760 6921 : std::pair<CAmount, std::pair<const CWalletTx*, unsigned int> > coinLowestLarger;
2761 6921 : coinLowestLarger.first = std::numeric_limits<CAmount>::max();
2762 6921 : coinLowestLarger.second.first = nullptr;
2763 13842 : std::vector<std::pair<CAmount, std::pair<const CWalletTx*, unsigned int> > > vValue;
2764 6921 : CAmount nTotalLower = 0;
2765 :
2766 6921 : Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
2767 :
2768 522588 : for (const COutput& output : vCoins) {
2769 516793 : if (!output.fSpendable)
2770 5590 : continue;
2771 :
2772 516793 : const CWalletTx* pcoin = output.tx;
2773 :
2774 1025580 : if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs)) {
2775 4913 : continue;
2776 : }
2777 :
2778 511880 : if (!mempool.TransactionWithinChainLimit(pcoin->GetHash(), nMaxAncestors)) {
2779 677 : continue;
2780 : }
2781 :
2782 511203 : int i = output.i;
2783 511203 : CAmount n = pcoin->tx->vout[i].nValue;
2784 :
2785 511203 : std::pair<CAmount, std::pair<const CWalletTx*, unsigned int> > coin = std::make_pair(n, std::make_pair(pcoin, i));
2786 :
2787 511203 : if (n == nTargetValue) {
2788 1126 : setCoinsRet.insert(coin.second);
2789 1126 : nValueRet += coin.first;
2790 1126 : return true;
2791 510077 : } else if (n < nTargetValue + MIN_CHANGE) {
2792 241030 : vValue.push_back(coin);
2793 241030 : nTotalLower += n;
2794 269047 : } else if (n < coinLowestLarger.first) {
2795 510077 : coinLowestLarger = coin;
2796 : }
2797 : }
2798 :
2799 5795 : if (nTotalLower == nTargetValue) {
2800 2409 : for (unsigned int i = 0; i < vValue.size(); ++i) {
2801 1906 : setCoinsRet.insert(vValue[i].second);
2802 1906 : nValueRet += vValue[i].first;
2803 : }
2804 : return true;
2805 : }
2806 :
2807 5292 : if (nTotalLower < nTargetValue) {
2808 3309 : if (coinLowestLarger.second.first == nullptr)
2809 : return false;
2810 2397 : setCoinsRet.insert(coinLowestLarger.second);
2811 2397 : nValueRet += coinLowestLarger.first;
2812 2397 : return true;
2813 : }
2814 :
2815 : // Solve subset sum by stochastic approximation
2816 1983 : std::sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
2817 8904 : std::vector<char> vfBest;
2818 1983 : CAmount nBest;
2819 :
2820 1983 : ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest);
2821 1983 : if (nBest != nTargetValue && nTotalLower >= nTargetValue + MIN_CHANGE)
2822 951 : ApproximateBestSubset(vValue, nTotalLower, nTargetValue + MIN_CHANGE, vfBest, nBest);
2823 :
2824 : // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
2825 : // or the next bigger coin is closer), return the bigger coin
2826 1983 : if (coinLowestLarger.second.first &&
2827 946 : ((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || coinLowestLarger.first <= nBest)) {
2828 316 : setCoinsRet.insert(coinLowestLarger.second);
2829 316 : nValueRet += coinLowestLarger.first;
2830 : } else {
2831 3334 : std::string s = "CWallet::SelectCoinsMinConf best subset: ";
2832 231258 : for (unsigned int i = 0; i < vValue.size(); i++) {
2833 229591 : if (vfBest[i]) {
2834 88293 : setCoinsRet.insert(vValue[i].second);
2835 88293 : nValueRet += vValue[i].first;
2836 176586 : s += FormatMoney(vValue[i].first) + " ";
2837 : }
2838 : }
2839 3334 : LogPrintf("%s - total %s\n", s, FormatMoney(nBest));
2840 : }
2841 :
2842 1983 : return true;
2843 : }
2844 :
2845 1088 : bool CWallet::SelectCoinsToSpend(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
2846 : {
2847 : // Note: this function should never be used for "always free" tx types like dstx
2848 2176 : std::vector<COutput> vCoins(vAvailableCoins);
2849 :
2850 : // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
2851 1088 : if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) {
2852 40 : for (const COutput& out : vCoins) {
2853 22 : if (!out.fSpendable)
2854 0 : continue;
2855 :
2856 22 : nValueRet += out.tx->tx->vout[out.i].nValue;
2857 44 : setCoinsRet.emplace(out.tx, out.i);
2858 : }
2859 18 : return (nValueRet >= nTargetValue);
2860 : }
2861 :
2862 : // calculate value from preset inputs and store them
2863 2158 : std::set<std::pair<const CWalletTx*, uint32_t> > setPresetCoins;
2864 1070 : CAmount nValueFromPresetInputs = 0;
2865 :
2866 2140 : std::vector<OutPointWrapper> vPresetInputs;
2867 1070 : if (coinControl)
2868 319 : coinControl->ListSelected(vPresetInputs);
2869 1088 : for (const auto& outpoint : vPresetInputs) {
2870 19 : std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.outPoint.hash);
2871 19 : if (it != mapWallet.end()) {
2872 18 : const CWalletTx* pcoin = &it->second;
2873 : // Clearly invalid input, fail
2874 18 : if (pcoin->tx->vout.size() <= outpoint.outPoint.n)
2875 0 : return false;
2876 18 : nValueFromPresetInputs += pcoin->tx->vout[outpoint.outPoint.n].nValue;
2877 18 : setPresetCoins.emplace(pcoin, outpoint.outPoint.n);
2878 : } else
2879 : return false; // TODO: Allow non-wallet inputs
2880 : }
2881 :
2882 : // remove preset inputs from vCoins
2883 2171 : for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();) {
2884 47 : if (setPresetCoins.count(std::make_pair(it->tx, it->i)))
2885 18 : it = vCoins.erase(it);
2886 : else
2887 1145 : ++it;
2888 : }
2889 :
2890 2138 : size_t nMaxChainLength = std::min(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT), gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT));
2891 :
2892 1010 : bool res = nTargetValue <= nValueFromPresetInputs ||
2893 1168 : SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet) ||
2894 1302 : SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, 0, vCoins, setCoinsRet, nValueRet) ||
2895 1144 : (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, 2, vCoins, setCoinsRet, nValueRet)) ||
2896 1130 : (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::min((size_t)4, nMaxChainLength/3), vCoins, setCoinsRet, nValueRet)) ||
2897 2163 : (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength/2, vCoins, setCoinsRet, nValueRet)) ||
2898 1100 : (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength, vCoins, setCoinsRet, nValueRet));
2899 :
2900 : // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
2901 1069 : setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
2902 :
2903 : // add preset inputs to the total value selected
2904 1069 : nValueRet += nValueFromPresetInputs;
2905 :
2906 1069 : return res;
2907 : }
2908 :
2909 0 : std::map<std::pair<CTxDestination, Optional<CTxDestination>>, std::vector<COutput>> CWallet::ListCoins() const
2910 : {
2911 0 : std::map<std::pair<CTxDestination, Optional<CTxDestination>>, std::vector<COutput>> result;
2912 :
2913 0 : CWallet::AvailableCoinsFilter filter;
2914 0 : filter.fIncludeLocked = true;
2915 0 : filter.fOnlySpendable = true;
2916 0 : std::vector<COutput> availableCoins;
2917 0 : AvailableCoins(&availableCoins, nullptr, filter);
2918 :
2919 0 : for (const COutput& coin : availableCoins) {
2920 0 : const CScript& scriptPubKey = coin.tx->tx->vout[coin.i].scriptPubKey;
2921 0 : txnouttype type; std::vector<CTxDestination> addresses; int nRequired;
2922 0 : if (ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
2923 0 : if (addresses.size() == 1) {
2924 : // P2PK, P2PKH scripts
2925 0 : const auto& addrpair = std::make_pair(addresses[0], nullopt);
2926 0 : result[addrpair].emplace_back(std::move(coin));
2927 0 : } else if (type == TX_COLDSTAKE) {
2928 : // P2CS scripts
2929 0 : assert(addresses.size() == 2);
2930 0 : const auto& addrpair = std::make_pair(addresses[1], Optional<CTxDestination>(addresses[0]));
2931 0 : result[addrpair].emplace_back(std::move(coin));
2932 : }
2933 : }
2934 : }
2935 :
2936 0 : return result;
2937 : }
2938 :
2939 0 : std::map<libzcash::SaplingPaymentAddress, std::vector<SaplingNoteEntry>> CWallet::ListNotes() const
2940 : {
2941 0 : return m_sspk_man->ListNotes();
2942 : }
2943 :
2944 22 : bool CWallet::CreateBudgetFeeTX(CTransactionRef& tx, const uint256& hash, CReserveKey& keyChange, CAmount fee)
2945 : {
2946 44 : CScript scriptChange;
2947 22 : scriptChange << OP_RETURN << ToByteVector(hash);
2948 :
2949 22 : CAmount nFeeRet = 0;
2950 44 : std::string strFail = "";
2951 44 : std::vector<CRecipient> vecSend;
2952 22 : vecSend.emplace_back(scriptChange, fee, false);
2953 :
2954 22 : CCoinControl* coinControl = nullptr;
2955 22 : int nChangePosInOut = -1;
2956 22 : bool success = CreateTransaction(vecSend, tx, keyChange, nFeeRet, nChangePosInOut, strFail, coinControl, true, (CAmount)0);
2957 22 : if (!success) {
2958 0 : LogPrintf("%s: Error - %s\n", __func__, strFail);
2959 : return false;
2960 : }
2961 :
2962 : return true;
2963 : }
2964 :
2965 130 : bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, const CTxDestination& destChange)
2966 : {
2967 130 : std::vector<CRecipient> vecSend;
2968 :
2969 : // Turn the txout set into a CRecipient vector.
2970 275 : for (size_t idx = 0; idx < tx.vout.size(); idx++) {
2971 145 : const CTxOut& txOut = tx.vout[idx];
2972 290 : vecSend.emplace_back(txOut.scriptPubKey, txOut.nValue, setSubtractFeeFromOutputs.count(idx) == 1);
2973 : }
2974 :
2975 260 : CCoinControl coinControl;
2976 130 : coinControl.destChange = destChange;
2977 130 : coinControl.fAllowOtherInputs = true;
2978 130 : coinControl.fAllowWatchOnly = includeWatching;
2979 130 : coinControl.fOverrideFeeRate = overrideEstimatedFeeRate;
2980 130 : coinControl.nFeeRate = specificFeeRate;
2981 :
2982 130 : const int nExtraSize = tx.isSaplingVersion() ?
2983 94 : (int)(GetSerializeSize(tx.sapData) + GetSerializeSize(tx.extraPayload)) : 0;
2984 :
2985 140 : for (const CTxIn& txin : tx.vin) {
2986 10 : coinControl.Select(txin.prevout);
2987 : }
2988 :
2989 : // Acquire the locks to prevent races to the new locked unspents between the
2990 : // CreateTransaction call and LockCoin calls (when lockUnspents is true).
2991 390 : LOCK2(cs_main, cs_wallet);
2992 :
2993 260 : CReserveKey reservekey(this);
2994 130 : CTransactionRef wtx;
2995 130 : if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, 0, false, nullptr, nExtraSize)) {
2996 : return false;
2997 : }
2998 :
2999 128 : if (nChangePosInOut != -1) {
3000 124 : tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx->vout[nChangePosInOut]);
3001 : // We don't have the normal Create/Commit cycle, and don't want to risk
3002 : // reusing change, so just remove the key from the keypool here.
3003 124 : reservekey.KeepKey();
3004 : }
3005 :
3006 : // Copy output sizes from new transaction; they may have had the fee
3007 : // subtracted from them.
3008 395 : for (unsigned int idx = 0; idx < tx.vout.size(); idx++) {
3009 267 : tx.vout[idx].nValue = wtx->vout[idx].nValue;
3010 : }
3011 :
3012 : // Add new txins while keeping original txin scriptSig/order.
3013 313 : for (const CTxIn& txin : wtx->vin) {
3014 185 : if (!coinControl.IsSelected(txin.prevout)) {
3015 176 : tx.vin.emplace_back(txin);
3016 176 : if (lockUnspents) LockCoin(txin.prevout);
3017 : }
3018 : }
3019 :
3020 128 : return true;
3021 : }
3022 :
3023 9 : std::vector<COutput> CWallet::GetOutputsFromCoinControl(const CCoinControl* coinControl)
3024 : {
3025 9 : assert(coinControl);
3026 9 : LOCK(cs_wallet);
3027 9 : std::vector<COutput> vCoinsRet;
3028 9 : std::vector<OutPointWrapper> vPresetInputs;
3029 9 : coinControl->ListSelected(vPresetInputs);
3030 20 : for (const auto& out : vPresetInputs) {
3031 11 : auto it = mapWallet.find(out.outPoint.hash);
3032 11 : if (it != mapWallet.end()) {
3033 11 : assert(it->second.tx->vout.size() > out.outPoint.n);
3034 11 : vCoinsRet.emplace_back(COutput(&(it->second), out.outPoint.n, 0, true, true, true));
3035 : }
3036 : }
3037 18 : return vCoinsRet;
3038 : }
3039 :
3040 506 : bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
3041 : CTransactionRef& txRet,
3042 : CReserveKey& reservekey,
3043 : CAmount& nFeeRet,
3044 : int& nChangePosInOut,
3045 : std::string& strFailReason,
3046 : const CCoinControl* coinControl,
3047 : bool sign,
3048 : CAmount nFeePay,
3049 : bool fIncludeDelegated,
3050 : bool* fStakeDelegationVoided,
3051 : int nExtraSize,
3052 : int nMinDepth)
3053 : {
3054 506 : CAmount nValue = 0;
3055 506 : int nChangePosRequest = nChangePosInOut;
3056 506 : unsigned int nSubtractFeeFromAmount = 0;
3057 1036 : for (const CRecipient& rec : vecSend) {
3058 530 : if (nValue < 0 || rec.nAmount < 0) {
3059 0 : strFailReason = _("Transaction amounts must be positive");
3060 0 : return false;
3061 : }
3062 530 : nValue += rec.nAmount;
3063 530 : if (rec.fSubtractFeeFromAmount)
3064 9 : nSubtractFeeFromAmount++;
3065 : }
3066 506 : if (vecSend.empty()) {
3067 0 : strFailReason = _("Transaction must have at least one recipient");
3068 0 : return false;
3069 : }
3070 :
3071 506 : CMutableTransaction txNew;
3072 1012 : CScript scriptChange;
3073 :
3074 506 : CWallet::AvailableCoinsFilter coinFilter;
3075 506 : coinFilter.fOnlySpendable = true;
3076 506 : coinFilter.fIncludeDelegated = fIncludeDelegated;
3077 506 : coinFilter.minDepth = nMinDepth;
3078 :
3079 506 : {
3080 506 : std::set<std::pair<const CWalletTx*,unsigned int> > setCoins;
3081 1512 : LOCK2(cs_main, cs_wallet);
3082 506 : {
3083 506 : std::vector<COutput> vAvailableCoins;
3084 506 : if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) {
3085 : // Select only the outputs that the caller pre-selected.
3086 18 : vAvailableCoins = GetOutputsFromCoinControl(coinControl);
3087 : } else {
3088 : // Regular selection
3089 497 : AvailableCoins(&vAvailableCoins, coinControl, coinFilter);
3090 : }
3091 :
3092 506 : nFeeRet = 0;
3093 506 : if (nFeePay > 0) nFeeRet = nFeePay;
3094 1088 : while (true) {
3095 1088 : nChangePosInOut = nChangePosRequest;
3096 1088 : txNew.vin.clear();
3097 1088 : txNew.vout.clear();
3098 1088 : bool fFirst = true;
3099 :
3100 1088 : CAmount nValueToSelect = nValue;
3101 1088 : if (nSubtractFeeFromAmount == 0)
3102 1074 : nValueToSelect += nFeeRet;
3103 :
3104 : // Fill outputs
3105 2227 : for (const CRecipient& rec : vecSend) {
3106 2278 : CTxOut txout(rec.nAmount, rec.scriptPubKey);
3107 1139 : if (rec.fSubtractFeeFromAmount) {
3108 18 : assert(nSubtractFeeFromAmount != 0);
3109 18 : txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
3110 :
3111 18 : if (fFirst) {
3112 : // first receiver pays the remainder not divisible by output count
3113 14 : fFirst = false;
3114 14 : txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
3115 : }
3116 : }
3117 1139 : if (IsDust(txout, dustRelayFee)) {
3118 0 : strFailReason = _("Transaction amount too small");
3119 0 : return false;
3120 : }
3121 1139 : txNew.vout.emplace_back(txout);
3122 : }
3123 :
3124 : // Choose coins to use
3125 1088 : CAmount nValueIn = 0;
3126 1088 : setCoins.clear();
3127 :
3128 1088 : if (!SelectCoinsToSpend(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl)) {
3129 2 : strFailReason = _("Insufficient funds.");
3130 2 : return false;
3131 : }
3132 :
3133 : // Change
3134 1086 : CAmount nChange = nValueIn - nValueToSelect;
3135 1086 : if (nChange > 0) {
3136 : // Fill a vout to ourself
3137 : // TODO: pass in scriptChange instead of reservekey so
3138 : // change transaction isn't always pay-to-pivx-address
3139 1000 : bool combineChange = false;
3140 :
3141 : // coin control: send change to custom address
3142 1000 : if (coinControl && IsValidDestination(coinControl->destChange)) {
3143 4 : scriptChange = GetScriptForDestination(coinControl->destChange);
3144 :
3145 4 : std::vector<CTxOut>::iterator it = txNew.vout.begin();
3146 6 : while (it != txNew.vout.end()) {
3147 4 : if (scriptChange == it->scriptPubKey) {
3148 2 : it->nValue += nChange;
3149 2 : nChange = 0;
3150 2 : reservekey.ReturnKey();
3151 : combineChange = true;
3152 : break;
3153 : }
3154 6 : ++it;
3155 : }
3156 : }
3157 :
3158 : // no coin control: send change to newly generated address
3159 : else {
3160 : // Note: We use a new key here to keep it from being obvious which side is the change.
3161 : // The drawback is that by not reusing a previous key, the change may be lost if a
3162 : // backup is restored, if the backup doesn't have the new private key for the change.
3163 : // If we reused the old key, it would be possible to add code to look for and
3164 : // rediscover unknown transactions that were written with keys of ours to recover
3165 : // post-backup change.
3166 :
3167 : // Reserve a new key pair from key pool. If it fails, provide a dummy
3168 996 : CPubKey vchPubKey;
3169 996 : if (!reservekey.GetReservedKey(vchPubKey, true)) {
3170 3 : strFailReason = _("Can't generate a change-address key. Please call keypoolrefill first.");
3171 3 : scriptChange = CScript();
3172 : } else {
3173 993 : scriptChange = GetScriptForDestination(vchPubKey.GetID());
3174 : }
3175 : }
3176 :
3177 1000 : if (!combineChange) {
3178 1996 : CTxOut newTxOut(nChange, scriptChange);
3179 :
3180 : // Never create dust outputs; if we would, just
3181 : // add the dust to the fee.
3182 998 : if (IsDust(newTxOut, dustRelayFee)) {
3183 3 : nFeeRet += nChange;
3184 3 : nChange = 0;
3185 3 : reservekey.ReturnKey();
3186 3 : nChangePosInOut = -1;
3187 : } else {
3188 995 : if (nChangePosInOut == -1) {
3189 : // Insert change txn at random position:
3190 993 : nChangePosInOut = GetRandInt(txNew.vout.size()+1);
3191 2 : } else if (nChangePosInOut < 0 || (unsigned int) nChangePosInOut > txNew.vout.size()) {
3192 0 : strFailReason = _("Change index out of range");
3193 0 : return false;
3194 : }
3195 995 : std::vector<CTxOut>::iterator position = txNew.vout.begin() + nChangePosInOut;
3196 995 : txNew.vout.insert(position, newTxOut);
3197 : }
3198 : }
3199 : } else {
3200 86 : reservekey.ReturnKey();
3201 86 : nChangePosInOut = -1;
3202 : }
3203 :
3204 : // Fill vin
3205 2572 : for (const std::pair<const CWalletTx*, unsigned int>& coin : setCoins) {
3206 1486 : if(fStakeDelegationVoided && coin.first->tx->vout[coin.second].scriptPubKey.IsPayToColdStaking()) {
3207 0 : *fStakeDelegationVoided = true;
3208 : }
3209 1486 : txNew.vin.emplace_back(coin.first->GetHash(), coin.second);
3210 : }
3211 :
3212 : // Fill in dummy signatures for fee calculation.
3213 1086 : int nIn = 0;
3214 2572 : for (const auto & coin : setCoins) {
3215 1486 : const CScript& scriptPubKey = coin.first->tx->vout[coin.second].scriptPubKey;
3216 2972 : SignatureData sigdata;
3217 2972 : if (!ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, txNew.GetRequiredSigVersion(), false)) {
3218 0 : strFailReason = _("Signing transaction failed");
3219 0 : return false;
3220 : } else {
3221 1486 : UpdateTransaction(txNew, nIn, sigdata);
3222 : }
3223 1486 : nIn++;
3224 : }
3225 :
3226 : // account for additional payloads in fee calculation
3227 1086 : const unsigned int nBytes = ::GetSerializeSize(txNew, PROTOCOL_VERSION) + nExtraSize;
3228 1086 : CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, nTxConfirmTarget, mempool));
3229 :
3230 : // Remove scriptSigs to eliminate the fee calculation dummy signatures
3231 2572 : for (CTxIn& vin : txNew.vin) {
3232 2972 : vin.scriptSig = CScript();
3233 : }
3234 :
3235 1086 : if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) {
3236 0 : nFeeNeeded = coinControl->nMinimumTotalFee;
3237 : }
3238 1086 : if (coinControl && coinControl->fOverrideFeeRate)
3239 8 : nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes);
3240 :
3241 : // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
3242 : // because we must be at the maximum allowed fee.
3243 1086 : if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes)) {
3244 0 : strFailReason = _("Transaction too large for fee policy");
3245 0 : return false;
3246 : }
3247 :
3248 1086 : if (nFeeRet >= nFeeNeeded) // Done, enough fee included
3249 : break;
3250 :
3251 : // Include more fee and try again.
3252 582 : nFeeRet = nFeeNeeded;
3253 582 : continue;
3254 582 : }
3255 :
3256 : // Give up if change keypool ran out and we failed to find a solution without change:
3257 504 : if (scriptChange.empty() && nChangePosInOut != -1) {
3258 : return false;
3259 : }
3260 : }
3261 :
3262 503 : if (sign) {
3263 750 : CTransaction txNewConst(txNew);
3264 375 : int nIn = 0;
3265 890 : for (const auto& coin : setCoins) {
3266 515 : const CScript& scriptPubKey = coin.first->tx->vout[coin.second].scriptPubKey;
3267 1030 : SignatureData sigdata;
3268 515 : bool haveKey = coin.first->GetStakeDelegationCredit() > 0;
3269 :
3270 515 : if (!ProduceSignature(
3271 1030 : TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->tx->vout[coin.second].nValue, SIGHASH_ALL),
3272 : scriptPubKey,
3273 : sigdata,
3274 : txNewConst.GetRequiredSigVersion(),
3275 515 : !haveKey // fColdStake
3276 : )) {
3277 0 : strFailReason = _("Signing transaction failed");
3278 0 : return false;
3279 : } else {
3280 515 : UpdateTransaction(txNew, nIn, sigdata);
3281 : }
3282 515 : nIn++;
3283 : }
3284 : }
3285 :
3286 : // Limit size
3287 503 : if (::GetSerializeSize(txNew, PROTOCOL_VERSION) >= MAX_STANDARD_TX_SIZE) {
3288 0 : strFailReason = _("Transaction too large");
3289 0 : return false;
3290 : }
3291 :
3292 : // Embed the constructed transaction data in wtxNew.
3293 503 : txRet = MakeTransactionRef(std::move(txNew));
3294 : }
3295 :
3296 : // Lastly, ensure this tx will pass the mempool's chain limits
3297 1009 : CTxMemPoolEntry entry(txRet, 0, 0, 0, false, 0);
3298 1006 : CTxMemPool::setEntries setAncestors;
3299 503 : size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
3300 503 : size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000;
3301 503 : size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
3302 503 : size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
3303 1006 : std::string errString;
3304 503 : if (!mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
3305 0 : strFailReason = _("Transaction has too long of a mempool chain");
3306 0 : return false;
3307 : }
3308 :
3309 : return true;
3310 : }
3311 :
3312 43 : bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, CTransactionRef& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, CAmount nFeePay, bool fIncludeDelegated, bool* fStakeDelegationVoided, int nExtraSize, int nMinDepth)
3313 : {
3314 86 : std::vector<CRecipient> vecSend;
3315 43 : vecSend.emplace_back(scriptPubKey, nValue, false);
3316 43 : int nChangePosInOut = -1;
3317 86 : return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, true, nFeePay, fIncludeDelegated, fStakeDelegationVoided, nExtraSize, nMinDepth);
3318 : }
3319 :
3320 12319 : int CWallet::GetLastBlockHeightLockWallet() const
3321 : {
3322 24638 : return WITH_LOCK(cs_wallet, return m_last_block_processed_height;);
3323 : }
3324 :
3325 1919 : bool CWallet::CreateCoinstakeOuts(const CPivStake& stakeInput, std::vector<CTxOut>& vout, CAmount nTotal) const
3326 : {
3327 1919 : std::vector<valtype> vSolutions;
3328 1919 : txnouttype whichType;
3329 3838 : CTxOut stakePrevout;
3330 1919 : if (!stakeInput.GetTxOutFrom(stakePrevout)) {
3331 0 : return error("%s: failed to get stake input", __func__);
3332 : }
3333 3838 : CScript scriptPubKeyKernel = stakePrevout.scriptPubKey;
3334 1919 : if (!Solver(scriptPubKeyKernel, whichType, vSolutions))
3335 0 : return error("%s: failed to parse kernel", __func__);
3336 :
3337 1919 : if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH && whichType != TX_COLDSTAKE)
3338 0 : return error("%s: type=%d (%s) not supported for scriptPubKeyKernel", __func__, whichType, GetTxnOutputType(whichType));
3339 :
3340 3838 : CKey key;
3341 1919 : if (whichType == TX_PUBKEYHASH || whichType == TX_COLDSTAKE) {
3342 : // if P2PKH or P2CS check that we have the input private key
3343 1869 : if (!GetKey(CKeyID(uint160(vSolutions[0])), key))
3344 0 : return error("%s: Unable to get staking private key", __func__);
3345 : }
3346 :
3347 1919 : vout.emplace_back(0, scriptPubKeyKernel);
3348 :
3349 : // Calculate if we need to split the output
3350 1919 : if (nStakeSplitThreshold > 0) {
3351 1919 : int nSplit = static_cast<int>(nTotal / nStakeSplitThreshold);
3352 1919 : if (nSplit > 1) {
3353 : // if nTotal is twice or more of the threshold; create more outputs
3354 19 : int txSizeMax = MAX_STANDARD_TX_SIZE >> 11; // limit splits to <10% of the max TX size (/2048)
3355 19 : if (nSplit > txSizeMax)
3356 0 : nSplit = txSizeMax;
3357 67 : for (int i = nSplit; i > 1; i--) {
3358 48 : LogPrintf("%s: StakeSplit: nTotal = %d; adding output %d of %d\n", __func__, nTotal, (nSplit-i)+2, nSplit);
3359 48 : vout.emplace_back(0, scriptPubKeyKernel);
3360 : }
3361 : }
3362 : }
3363 :
3364 : return true;
3365 : }
3366 :
3367 1925 : bool CWallet::CreateCoinStake(
3368 : const CBlockIndex* pindexPrev,
3369 : unsigned int nBits,
3370 : CMutableTransaction& txNew,
3371 : int64_t& nTxNewTime,
3372 : std::vector<CStakeableOutput>* availableCoins,
3373 : bool stopOnNewBlock) const
3374 : {
3375 : // shuffle coins
3376 1925 : if (availableCoins && Params().IsRegTestNet()) {
3377 1925 : Shuffle(availableCoins->begin(), availableCoins->end(), FastRandomContext());
3378 : }
3379 :
3380 : // Mark coin stake transaction
3381 1925 : txNew.vin.clear();
3382 1925 : txNew.vout.clear();
3383 1925 : txNew.vout.emplace_back(0, CScript());
3384 :
3385 : // update staker status (hash)
3386 1925 : pStakerStatus->SetLastTip(pindexPrev);
3387 1925 : pStakerStatus->SetLastCoins((int) availableCoins->size());
3388 :
3389 : // Kernel Search
3390 1925 : CAmount nCredit;
3391 1925 : CAmount nMasternodePayment;
3392 3850 : CScript scriptPubKeyKernel;
3393 1925 : bool fKernelFound = false;
3394 1925 : int nAttempts = 0;
3395 12775 : for (auto it = availableCoins->begin(); it != availableCoins->end();) {
3396 12769 : COutPoint outPoint = COutPoint(it->tx->GetHash(), it->i);
3397 12769 : CPivStake stakeInput(it->tx->tx->vout[it->i],
3398 : outPoint,
3399 12769 : it->pindex);
3400 :
3401 : // New block came in, move on
3402 12769 : if (stopOnNewBlock && GetLastBlockHeightLockWallet() != pindexPrev->nHeight) return false;
3403 :
3404 : // Make sure the wallet is unlocked and shutdown hasn't been requested
3405 12769 : if (IsLocked() || ShutdownRequested()) return false;
3406 :
3407 : // Make sure the stake input hasn't been spent since last check
3408 38307 : if (WITH_LOCK(cs_wallet, return IsSpent(outPoint))) {
3409 : // remove it from the available coins
3410 43 : it = availableCoins->erase(it);
3411 10893 : continue;
3412 : }
3413 :
3414 12726 : nCredit = 0;
3415 :
3416 12726 : nAttempts++;
3417 12726 : fKernelFound = Stake(pindexPrev, &stakeInput, nBits, nTxNewTime);
3418 :
3419 : // update staker status (time, attempts)
3420 12726 : pStakerStatus->SetLastTime(nTxNewTime);
3421 12726 : pStakerStatus->SetLastTries(nAttempts);
3422 :
3423 12726 : if (!fKernelFound) {
3424 10807 : it++;
3425 10807 : continue;
3426 : }
3427 :
3428 : // Found a kernel
3429 1919 : LogPrintf("CreateCoinStake : kernel found\n");
3430 1919 : nCredit += stakeInput.GetValue();
3431 :
3432 : // Add block reward to the credit
3433 1919 : nCredit += GetBlockValue(pindexPrev->nHeight + 1);
3434 1919 : nMasternodePayment = GetMasternodePayment(pindexPrev->nHeight + 1);
3435 :
3436 : // Create the output transaction(s)
3437 1919 : std::vector<CTxOut> vout;
3438 1919 : if (!CreateCoinstakeOuts(stakeInput, vout, nCredit - nMasternodePayment)) {
3439 0 : LogPrintf("%s : failed to create output\n", __func__);
3440 0 : it++;
3441 0 : continue;
3442 : }
3443 1919 : txNew.vout.insert(txNew.vout.end(), vout.begin(), vout.end());
3444 :
3445 : // Set output amount
3446 1919 : int outputs = (int) txNew.vout.size() - 1;
3447 1919 : CAmount nRemaining = nCredit;
3448 1919 : if (outputs > 1) {
3449 : // Split the stake across the outputs
3450 19 : CAmount nShare = nRemaining / outputs;
3451 67 : for (int i = 1; i < outputs; i++) {
3452 : // loop through all but the last one.
3453 48 : txNew.vout[i].nValue = nShare;
3454 48 : nRemaining -= nShare;
3455 : }
3456 : }
3457 : // put the remaining on the last output (which all into the first if only one output)
3458 1919 : txNew.vout[outputs].nValue += nRemaining;
3459 :
3460 : // Set coinstake input
3461 1919 : txNew.vin.emplace_back(stakeInput.GetTxIn());
3462 :
3463 : // Limit size
3464 1919 : unsigned int nBytes = ::GetSerializeSize(txNew, PROTOCOL_VERSION);
3465 1919 : if (nBytes >= DEFAULT_BLOCK_MAX_SIZE / 5)
3466 0 : return error("%s : exceeded coinstake size limit", __func__);
3467 :
3468 1919 : break;
3469 : }
3470 1925 : LogPrint(BCLog::STAKING, "%s: attempted staking %d times\n", __func__, nAttempts);
3471 :
3472 : return fKernelFound;
3473 : }
3474 :
3475 1919 : bool CWallet::SignCoinStake(CMutableTransaction& txNew) const
3476 : {
3477 : // Sign it
3478 1919 : int nIn = 0;
3479 3838 : for (const CTxIn& txIn : txNew.vin) {
3480 1919 : const CWalletTx* wtx = GetWalletTx(txIn.prevout.hash);
3481 1919 : if (!wtx || !SignSignature(*this, *(wtx->tx), txNew, nIn++, SIGHASH_ALL, true))
3482 0 : return error("%s : failed to sign coinstake", __func__);
3483 : }
3484 :
3485 : // Successfully signed coinstake
3486 1919 : return true;
3487 : }
3488 :
3489 7 : std::string CWallet::CommitResult::ToString() const
3490 : {
3491 21 : std::string strErrRet = strprintf(_("Failed to accept tx in the memory pool (reason: %s)\n"), FormatStateMessage(state));
3492 :
3493 7 : switch (status) {
3494 0 : case CWallet::CommitStatus::OK:
3495 0 : return _("No error");
3496 7 : case CWallet::CommitStatus::Abandoned:
3497 14 : strErrRet += _("Transaction canceled.");
3498 7 : break;
3499 0 : case CWallet::CommitStatus::NotAccepted:
3500 0 : strErrRet += strprintf(_("WARNING: The transaction has been signed and recorded, so the wallet will try to re-send it. "
3501 0 : "Use 'abandontransaction' to cancel it. (txid: %s)"), hashTx.ToString());
3502 0 : break;
3503 0 : default:
3504 0 : return _("Invalid status error.");
3505 : }
3506 :
3507 14 : return strErrRet;
3508 : }
3509 :
3510 374 : CWallet::CommitResult CWallet::CommitTransaction(CTransactionRef tx, CReserveKey& opReservekey, CConnman* connman)
3511 : {
3512 748 : return CommitTransaction(std::move(tx), &opReservekey, connman);
3513 : }
3514 :
3515 : /**
3516 : * Call after CreateTransaction unless you want to abort
3517 : */
3518 1441 : CWallet::CommitResult CWallet::CommitTransaction(CTransactionRef tx, CReserveKey* opReservekey, CConnman* connman, mapValue_t* extras)
3519 : {
3520 1441 : CommitResult res;
3521 :
3522 2882 : CWalletTx wtxNew(this, std::move(tx));
3523 1441 : wtxNew.fTimeReceivedIsTxTime = true;
3524 1441 : wtxNew.BindWallet(this);
3525 1441 : wtxNew.fFromMe = true;
3526 1441 : wtxNew.fStakeDelegationVoided = wtxNew.tx->HasP2CSOutputs();
3527 1441 : if (extras) wtxNew.mapValue.insert(extras->begin(), extras->end());
3528 :
3529 1441 : {
3530 4315 : LOCK2(cs_main, cs_wallet);
3531 1441 : LogPrintf("%s: %s\n", __func__, wtxNew.tx->ToString());
3532 1441 : {
3533 : // Take key pair from key pool so it won't be used again
3534 1441 : if (opReservekey) opReservekey->KeepKey();
3535 :
3536 : // Add tx to wallet, because if it has change it's also ours,
3537 : // otherwise just for transaction history.
3538 1441 : AddToWallet(wtxNew);
3539 :
3540 : // Notify that old coins are spent
3541 1441 : if (!wtxNew.tx->HasZerocoinSpendInputs()) {
3542 2882 : std::set<uint256> updated_hashes;
3543 3011 : for (const CTxIn& txin : wtxNew.tx->vin) {
3544 : // notify only once
3545 1570 : if (updated_hashes.find(txin.prevout.hash) != updated_hashes.end()) continue;
3546 :
3547 1566 : CWalletTx& coin = mapWallet.at(txin.prevout.hash);
3548 1566 : coin.BindWallet(this);
3549 1566 : NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
3550 3136 : updated_hashes.insert(txin.prevout.hash);
3551 : }
3552 : }
3553 : }
3554 :
3555 1441 : res.hashTx = wtxNew.GetHash();
3556 :
3557 : // Get the inserted-CWalletTx from mapWallet so that the
3558 : // fInMempool flag is cached properly
3559 1441 : CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
3560 :
3561 : // Try ATMP. This must not fail. The transaction has already been signed and recorded.
3562 2878 : CValidationState state;
3563 1441 : if (!wtx.AcceptToMemoryPool(state)) {
3564 4 : res.state = state;
3565 : // Abandon the transaction
3566 4 : if (AbandonTransaction(res.hashTx)) {
3567 4 : res.status = CWallet::CommitStatus::Abandoned;
3568 : // Return the change key
3569 4 : if (opReservekey) opReservekey->ReturnKey();
3570 : }
3571 :
3572 4 : LogPrintf("%s: ERROR: %s\n", __func__, res.ToString());
3573 4 : return res;
3574 : }
3575 :
3576 1437 : res.status = CWallet::CommitStatus::OK;
3577 :
3578 : // Broadcast
3579 1437 : wtx.RelayWalletTransaction(connman);
3580 : }
3581 : return res;
3582 : }
3583 :
3584 404 : DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
3585 : {
3586 1211 : LOCK2(cs_main, cs_wallet);
3587 :
3588 404 : DBErrors nLoadWalletRet = WalletBatch(*database, "cr+").LoadWallet(this);
3589 403 : if (nLoadWalletRet == DB_NEED_REWRITE) {
3590 0 : if (database->Rewrite( "\x04pool")) {
3591 : // TODO: Implement spk_man->RewriteDB().
3592 0 : m_spk_man->set_pre_split_keypool.clear();
3593 : // Note: can't top-up keypool here, because wallet is locked.
3594 : // User will be prompted to unlock wallet the next operation
3595 : // the requires a new key.
3596 : }
3597 : }
3598 :
3599 : // This wallet is in its first run if all of these are empty
3600 403 : fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapMasterKeys.empty() && setWatchOnly.empty() && mapScripts.empty();
3601 :
3602 403 : if (nLoadWalletRet != DB_LOAD_OK)
3603 : return nLoadWalletRet;
3604 :
3605 403 : uiInterface.LoadWallet(this);
3606 :
3607 : return DB_LOAD_OK;
3608 : }
3609 :
3610 :
3611 5 : DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
3612 : {
3613 5 : DBErrors nZapWalletTxRet = WalletBatch(*database, "cr+").ZapWalletTx(this, vWtx);
3614 5 : if (nZapWalletTxRet == DB_NEED_REWRITE) {
3615 0 : if (database->Rewrite("\x04pool")) {
3616 0 : LOCK(cs_wallet);
3617 0 : m_spk_man->set_pre_split_keypool.clear();
3618 : // Note: can't top-up keypool here, because wallet is locked.
3619 : // User will be prompted to unlock wallet the next operation
3620 : // that requires a new key.
3621 : }
3622 : }
3623 :
3624 5 : if (nZapWalletTxRet != DB_LOAD_OK)
3625 0 : return nZapWalletTxRet;
3626 :
3627 : return DB_LOAD_OK;
3628 : }
3629 :
3630 3768 : std::string CWallet::ParseIntoAddress(const CWDestination& dest, const std::string& purpose) {
3631 3768 : CChainParams::Base58Type addrType;
3632 3768 : if (AddressBook::IsColdStakingPurpose(purpose)) {
3633 : addrType = CChainParams::STAKING_ADDRESS;
3634 3741 : } else if (AddressBook::IsExchangePurpose(purpose)) {
3635 : addrType = CChainParams::EXCHANGE_ADDRESS;
3636 : } else {
3637 3741 : addrType = CChainParams::PUBKEY_ADDRESS;
3638 : }
3639 3768 : return Standard::EncodeDestination(dest, addrType);
3640 : }
3641 :
3642 3768 : bool CWallet::SetAddressBook(const CWDestination& address, const std::string& strName, const std::string& strPurpose)
3643 : {
3644 3768 : bool fUpdated = HasAddressBook(address);
3645 3768 : {
3646 3768 : LOCK(cs_wallet); // mapAddressBook
3647 3768 : mapAddressBook[address].name = strName;
3648 3768 : if (!strPurpose.empty()) /* update purpose only if requested */
3649 3768 : mapAddressBook[address].purpose = strPurpose;
3650 : }
3651 7536 : NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
3652 3768 : mapAddressBook.at(address).purpose, (fUpdated ? CT_UPDATED : CT_NEW));
3653 7536 : std::string addressStr = ParseIntoAddress(address, mapAddressBook.at(address).purpose);
3654 7518 : if (!strPurpose.empty() && !WalletBatch(*database).WritePurpose(addressStr, strPurpose))
3655 : return false;
3656 3768 : return WalletBatch(*database).WriteName(addressStr, strName);
3657 : }
3658 :
3659 0 : bool CWallet::DelAddressBook(const CWDestination& address, const CChainParams::Base58Type addrType)
3660 : {
3661 0 : std::string strAddress = Standard::EncodeDestination(address, addrType);
3662 0 : std::string purpose = GetPurposeForAddressBookEntry(address);
3663 0 : {
3664 0 : LOCK(cs_wallet); // mapAddressBook
3665 :
3666 : // Delete destdata tuples associated with address
3667 0 : for (const std::pair<std::string, std::string> & item : mapAddressBook[address].destdata) {
3668 0 : WalletBatch(*database).EraseDestData(strAddress, item.first);
3669 : }
3670 0 : mapAddressBook.erase(address);
3671 : }
3672 :
3673 0 : NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, purpose, CT_DELETED);
3674 :
3675 0 : WalletBatch(*database).ErasePurpose(strAddress);
3676 0 : return WalletBatch(*database).EraseName(strAddress);
3677 : }
3678 :
3679 0 : std::string CWallet::GetPurposeForAddressBookEntry(const CWDestination& address) const
3680 : {
3681 0 : LOCK(cs_wallet);
3682 0 : auto it = mapAddressBook.find(address);
3683 0 : return it != mapAddressBook.end() ? it->second.purpose : "";
3684 : }
3685 :
3686 1925350 : std::string CWallet::GetNameForAddressBookEntry(const CWDestination& address) const
3687 : {
3688 1925350 : LOCK(cs_wallet);
3689 1925350 : auto it = mapAddressBook.find(address);
3690 5776050 : return it != mapAddressBook.end() ? it->second.name : "";
3691 : }
3692 :
3693 553 : Optional<AddressBook::CAddressBookData> CWallet::GetAddressBookEntry(const CWDestination& dest) const
3694 : {
3695 553 : LOCK(cs_wallet);
3696 553 : auto it = mapAddressBook.find(dest);
3697 1534 : return it != mapAddressBook.end() ? Optional<AddressBook::CAddressBookData>(it->second) : nullopt;
3698 : }
3699 :
3700 260 : void CWallet::LoadAddressBookName(const CWDestination& dest, const std::string& strName)
3701 : {
3702 260 : mapAddressBook[dest].name = strName;
3703 260 : }
3704 :
3705 260 : void CWallet::LoadAddressBookPurpose(const CWDestination& dest, const std::string& strPurpose)
3706 : {
3707 260 : mapAddressBook[dest].purpose = strPurpose;
3708 260 : }
3709 :
3710 1976303 : bool CWallet::HasAddressBook(const CWDestination& address) const
3711 : {
3712 7905232 : return WITH_LOCK(cs_wallet, return mapAddressBook.count(address));
3713 : }
3714 :
3715 91 : bool CWallet::HasDelegator(const CTxOut& out) const
3716 : {
3717 182 : CTxDestination delegator;
3718 91 : if (!ExtractDestination(out.scriptPubKey, delegator, false))
3719 : return false;
3720 91 : {
3721 182 : LOCK(cs_wallet); // mapAddressBook
3722 91 : const auto mi = mapAddressBook.find(delegator);
3723 91 : if (mi == mapAddressBook.end())
3724 : return false;
3725 91 : return (*mi).second.purpose == AddressBook::AddressBookPurpose::DELEGATOR;
3726 : }
3727 : }
3728 :
3729 67 : size_t CWallet::KeypoolCountExternalKeys()
3730 : {
3731 67 : return m_spk_man->KeypoolCountExternalKeys();
3732 : }
3733 :
3734 2499 : bool CWallet::TopUpKeyPool(unsigned int kpSize)
3735 : {
3736 2499 : return m_spk_man->TopUp(kpSize);
3737 : }
3738 :
3739 4186 : void CWallet::KeepKey(int64_t nIndex)
3740 : {
3741 4186 : m_spk_man->KeepDestination(nIndex);
3742 4186 : }
3743 :
3744 15 : void CWallet::ReturnKey(int64_t nIndex, const bool internal, const bool staking)
3745 : {
3746 : // Return to key pool
3747 15 : CTxDestination address; // This is not needed for now.
3748 15 : uint8_t changeType = staking ? HDChain::ChangeType::STAKING : (internal ? HDChain::ChangeType::INTERNAL : HDChain::ChangeType::EXTERNAL);
3749 15 : m_spk_man->ReturnDestination(nIndex, changeType, address);
3750 15 : }
3751 :
3752 2289 : bool CWallet::GetKeyFromPool(CPubKey& result, const uint8_t& type)
3753 : {
3754 2289 : return m_spk_man->GetKeyFromPool(result, type);
3755 : }
3756 :
3757 67 : int64_t CWallet::GetOldestKeyPoolTime()
3758 : {
3759 268 : return WITH_LOCK(cs_wallet, return std::min(std::numeric_limits<int64_t>::max(), m_spk_man->GetOldestKeyPoolTime()));
3760 : }
3761 :
3762 1 : std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
3763 : {
3764 1 : std::map<CTxDestination, CAmount> balances;
3765 :
3766 1 : {
3767 1 : LOCK(cs_wallet);
3768 103 : for (const auto& walletEntry : mapWallet) {
3769 102 : const CWalletTx* pcoin = &walletEntry.second;
3770 :
3771 102 : if (!IsFinalTx(pcoin->tx, m_last_block_processed_height) || !pcoin->IsTrusted())
3772 100 : continue;
3773 :
3774 102 : if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
3775 100 : continue;
3776 :
3777 2 : bool fConflicted;
3778 2 : int nDepth = pcoin->GetDepthAndMempool(fConflicted);
3779 2 : if (fConflicted)
3780 0 : continue;
3781 4 : if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
3782 0 : continue;
3783 :
3784 4 : for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
3785 4 : CTxDestination addr;
3786 2 : if (!IsMine(pcoin->tx->vout[i]))
3787 0 : continue;
3788 2 : if ( !ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr) &&
3789 0 : !ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr, true) )
3790 0 : continue;
3791 :
3792 2 : CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
3793 :
3794 2 : if (!balances.count(addr))
3795 2 : balances[addr] = 0;
3796 2 : balances[addr] += n;
3797 : }
3798 : }
3799 : }
3800 :
3801 1 : return balances;
3802 : }
3803 :
3804 1 : std::set<std::set<CTxDestination> > CWallet::GetAddressGroupings()
3805 : {
3806 1 : AssertLockHeld(cs_wallet); // mapWallet
3807 1 : std::set<std::set<CTxDestination> > groupings;
3808 1 : std::set<CTxDestination> grouping;
3809 :
3810 103 : for (const auto& walletEntry : mapWallet) {
3811 102 : const CWalletTx* pcoin = &walletEntry.second;
3812 :
3813 102 : if (pcoin->tx->vin.size() > 0) {
3814 102 : bool any_mine = false;
3815 : // group all input addresses with each other
3816 204 : for (CTxIn txin : pcoin->tx->vin) {
3817 102 : CTxDestination address;
3818 102 : if (!IsMine(txin)) /* If this input isn't mine, ignore it */
3819 204 : continue;
3820 0 : if (!ExtractDestination(mapWallet.at(txin.prevout.hash).tx->vout[txin.prevout.n].scriptPubKey, address))
3821 0 : continue;
3822 0 : grouping.insert(address);
3823 0 : any_mine = true;
3824 : }
3825 :
3826 : // group change with input addresses
3827 102 : if (any_mine) {
3828 0 : for (CTxOut txout : pcoin->tx->vout)
3829 0 : if (IsChange(txout)) {
3830 0 : CTxDestination txoutAddr;
3831 0 : if (!ExtractDestination(txout.scriptPubKey, txoutAddr))
3832 0 : continue;
3833 0 : grouping.insert(txoutAddr);
3834 : }
3835 : }
3836 102 : if (grouping.size() > 0) {
3837 0 : groupings.insert(grouping);
3838 0 : grouping.clear();
3839 : }
3840 : }
3841 :
3842 : // group lone addrs by themselves
3843 204 : for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
3844 102 : if (IsMine(pcoin->tx->vout[i])) {
3845 204 : CTxDestination address;
3846 102 : if (!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, address))
3847 0 : continue;
3848 102 : grouping.insert(address);
3849 102 : groupings.insert(grouping);
3850 102 : grouping.clear();
3851 : }
3852 : }
3853 :
3854 2 : std::set<std::set<CTxDestination>*> uniqueGroupings; // a set of pointers to groups of addresses
3855 2 : std::map<CTxDestination, std::set<CTxDestination>*> setmap; // map addresses to the unique group containing it
3856 3 : for (std::set<CTxDestination> grouping : groupings) {
3857 : // make a set of all the groups hit by this new group
3858 4 : std::set<std::set<CTxDestination>*> hits;
3859 2 : std::map<CTxDestination, std::set<CTxDestination>*>::iterator it;
3860 4 : for (CTxDestination address : grouping)
3861 2 : if ((it = setmap.find(address)) != setmap.end())
3862 2 : hits.insert((*it).second);
3863 :
3864 : // merge all hit groups into a new single group and delete old groups
3865 2 : std::set<CTxDestination>* merged = new std::set<CTxDestination>(grouping);
3866 2 : for (std::set<CTxDestination>* hit : hits) {
3867 0 : merged->insert(hit->begin(), hit->end());
3868 0 : uniqueGroupings.erase(hit);
3869 0 : delete hit;
3870 : }
3871 2 : uniqueGroupings.insert(merged);
3872 :
3873 : // update setmap
3874 4 : for (CTxDestination element : *merged)
3875 2 : setmap[element] = merged;
3876 : }
3877 :
3878 1 : std::set<std::set<CTxDestination> > ret;
3879 3 : for (std::set<CTxDestination>* uniqueGrouping : uniqueGroupings) {
3880 2 : ret.insert(*uniqueGrouping);
3881 4 : delete uniqueGrouping;
3882 : }
3883 :
3884 2 : return ret;
3885 : }
3886 :
3887 14 : std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
3888 : {
3889 14 : LOCK(cs_wallet);
3890 14 : std::set<CTxDestination> result;
3891 100 : for (const auto& item : mapAddressBook) {
3892 86 : if (item.second.isShielded()) continue;
3893 86 : const auto& address = boost::get<CTxDestination>(item.first);
3894 86 : const std::string& strName = item.second.name;
3895 86 : if (strName == label)
3896 117 : result.insert(address);
3897 : }
3898 28 : return result;
3899 : }
3900 :
3901 5731 : bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool _internal)
3902 : {
3903 :
3904 5731 : ScriptPubKeyMan* m_spk_man = pwallet->GetScriptPubKeyMan();
3905 5731 : if (!m_spk_man) {
3906 : return false;
3907 : }
3908 :
3909 5731 : if (nIndex == -1) {
3910 :
3911 : // Fill the pool if needed
3912 4205 : m_spk_man->TopUp();
3913 4205 : internal = _internal;
3914 :
3915 : // Modify this for Staking addresses support if needed.
3916 4205 : uint8_t changeType = internal ? HDChain::ChangeType::INTERNAL : HDChain::ChangeType::EXTERNAL;
3917 4205 : CKeyPool keypool;
3918 4205 : if (!m_spk_man->GetReservedKey(changeType, nIndex, keypool))
3919 4 : return false;
3920 :
3921 4201 : if (nIndex != -1)
3922 4201 : vchPubKey = keypool.vchPubKey;
3923 : else {
3924 : return false;
3925 : }
3926 : }
3927 5727 : assert(vchPubKey.IsValid());
3928 5727 : pubkey = vchPubKey;
3929 5727 : return true;
3930 : }
3931 :
3932 4190 : void CReserveKey::KeepKey()
3933 : {
3934 4190 : if (nIndex != -1)
3935 4186 : pwallet->KeepKey(nIndex);
3936 4190 : nIndex = -1;
3937 4190 : vchPubKey = CPubKey();
3938 4190 : }
3939 :
3940 4306 : void CReserveKey::ReturnKey()
3941 : {
3942 4306 : if (nIndex != -1)
3943 15 : pwallet->ReturnKey(nIndex, internal);
3944 4306 : nIndex = -1;
3945 4306 : vchPubKey = CPubKey();
3946 4306 : }
3947 :
3948 176 : void CWallet::LockCoin(const COutPoint& output)
3949 : {
3950 176 : AssertLockHeld(cs_wallet); // setLockedCoins
3951 176 : setLockedCoins.insert(output);
3952 176 : }
3953 :
3954 1 : void CWallet::LockNote(const SaplingOutPoint& op)
3955 : {
3956 1 : AssertLockHeld(cs_wallet); // setLockedNotes
3957 1 : setLockedNotes.insert(op);
3958 1 : }
3959 :
3960 1 : void CWallet::UnlockCoin(const COutPoint& output)
3961 : {
3962 1 : AssertLockHeld(cs_wallet); // setLockedCoins
3963 1 : setLockedCoins.erase(output);
3964 1 : }
3965 :
3966 1 : void CWallet::UnlockNote(const SaplingOutPoint& op)
3967 : {
3968 1 : AssertLockHeld(cs_wallet); // setLockedNotes
3969 1 : setLockedNotes.erase(op);
3970 1 : }
3971 :
3972 0 : void CWallet::UnlockAllCoins()
3973 : {
3974 0 : AssertLockHeld(cs_wallet); // setLockedCoins
3975 0 : setLockedCoins.clear();
3976 0 : }
3977 :
3978 0 : void CWallet::UnlockAllNotes()
3979 : {
3980 0 : AssertLockHeld(cs_wallet); // setLockedNotes
3981 0 : setLockedNotes.clear();
3982 0 : }
3983 :
3984 3430538 : bool CWallet::IsLockedCoin(const uint256& hash, unsigned int n) const
3985 : {
3986 3430538 : AssertLockHeld(cs_wallet); // setLockedCoins
3987 3430538 : const COutPoint outpt(hash, n);
3988 :
3989 3430538 : return (setLockedCoins.count(outpt) > 0);
3990 : }
3991 :
3992 541 : bool CWallet::IsLockedNote(const SaplingOutPoint& op) const
3993 : {
3994 541 : AssertLockHeld(cs_wallet); // setLockedNotes
3995 541 : return (setLockedNotes.count(op) > 0);
3996 : }
3997 :
3998 52 : std::set<COutPoint> CWallet::ListLockedCoins()
3999 : {
4000 52 : AssertLockHeld(cs_wallet); // setLockedCoins
4001 52 : return setLockedCoins;
4002 : }
4003 :
4004 52 : std::set<SaplingOutPoint> CWallet::ListLockedNotes()
4005 : {
4006 52 : AssertLockHeld(cs_wallet); // setLockedNotes
4007 52 : return setLockedNotes;
4008 : }
4009 :
4010 0 : bool CWallet::SetStakeSplitThreshold(const CAmount sst)
4011 : {
4012 0 : LOCK(cs_wallet);
4013 0 : if (nStakeSplitThreshold != sst) {
4014 0 : nStakeSplitThreshold = sst;
4015 0 : if (!WalletBatch(*database).WriteStakeSplitThreshold(sst)) {
4016 : return false;
4017 : }
4018 0 : NotifySSTChanged(sst);
4019 : }
4020 : return true;
4021 : }
4022 :
4023 : /** @} */ // end of Actions
4024 :
4025 :
4026 8 : void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const
4027 : {
4028 8 : AssertLockHeld(cs_wallet); // mapKeyMetadata
4029 8 : mapKeyBirth.clear();
4030 :
4031 : // get birth times for keys with metadata
4032 1981 : for (const auto& entry : mapKeyMetadata) {
4033 1973 : if (entry.second.nCreateTime) mapKeyBirth[entry.first] = entry.second.nCreateTime;
4034 : }
4035 :
4036 : // map in which we'll infer heights of other keys
4037 10 : CBlockIndex* pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
4038 8 : std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
4039 1981 : for (const CKeyID& keyid : GetKeys()) {
4040 3946 : if (mapKeyBirth.count(keyid) == 0)
4041 0 : mapKeyFirstBlock[keyid] = pindexMax;
4042 : }
4043 :
4044 : // if there are no such keys, we're done
4045 8 : if (mapKeyFirstBlock.empty())
4046 8 : return;
4047 :
4048 : // find first block that affects those keys, if there are any left
4049 0 : std::vector<CKeyID> vAffected;
4050 0 : for (const auto& entry : mapWallet) {
4051 : // iterate over all wallet transactions...
4052 0 : const CWalletTx& wtx = entry.second;
4053 0 : CBlockIndex* pindex = LookupBlockIndex(wtx.m_confirm.hashBlock);
4054 0 : if (pindex && chainActive.Contains(pindex)) {
4055 : // ... which are already in a block
4056 0 : int nHeight = pindex->nHeight;
4057 0 : for (const CTxOut& txout : wtx.tx->vout) {
4058 : // iterate over all their outputs
4059 0 : CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
4060 0 : for (const CKeyID& keyid : vAffected) {
4061 : // ... and all their affected keys
4062 0 : std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
4063 0 : if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
4064 0 : rit->second = pindex;
4065 : }
4066 0 : vAffected.clear();
4067 : }
4068 : }
4069 : }
4070 :
4071 : // Extract block timestamps for those keys
4072 0 : for (const auto& entry : mapKeyFirstBlock)
4073 0 : mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
4074 : }
4075 :
4076 0 : bool CWallet::AddDestData(const CTxDestination& dest, const std::string& key, const std::string& value)
4077 : {
4078 0 : if (!IsValidDestination(dest))
4079 : return false;
4080 :
4081 0 : mapAddressBook[dest].destdata.emplace(key, value);
4082 0 : return WalletBatch(*database).WriteDestData(EncodeDestination(dest), key, value);
4083 : }
4084 :
4085 0 : bool CWallet::EraseDestData(const CTxDestination& dest, const std::string& key)
4086 : {
4087 0 : if (!mapAddressBook[dest].destdata.erase(key))
4088 : return false;
4089 0 : return WalletBatch(*database).EraseDestData(EncodeDestination(dest), key);
4090 : }
4091 :
4092 0 : bool CWallet::LoadDestData(const CTxDestination& dest, const std::string& key, const std::string& value)
4093 : {
4094 0 : mapAddressBook[dest].destdata.emplace(key, value);
4095 0 : return true;
4096 : }
4097 :
4098 0 : std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
4099 : {
4100 0 : LOCK(cs_wallet);
4101 0 : std::vector<std::string> values;
4102 0 : for (const auto& address : mapAddressBook) {
4103 0 : for (const auto& data : address.second.destdata) {
4104 0 : if (!data.first.compare(0, prefix.size(), prefix)) {
4105 0 : values.emplace_back(data.second);
4106 : }
4107 : }
4108 : }
4109 0 : return values;
4110 : }
4111 :
4112 1 : void CWallet::AutoCombineDust(CConnman* connman)
4113 : {
4114 1 : {
4115 1 : LOCK(cs_wallet);
4116 1 : if (m_last_block_processed.IsNull() ||
4117 2 : m_last_block_processed_time < (GetAdjustedTime() - 300) ||
4118 1 : IsLocked()) {
4119 0 : return;
4120 : }
4121 : }
4122 :
4123 1 : std::map<CTxDestination, std::vector<COutput> > mapCoinsByAddress =
4124 2 : AvailableCoinsByAddress(true, nAutoCombineThreshold, false);
4125 :
4126 : //coins are sectioned by address. This combination code only wants to combine inputs that belong to the same address
4127 2 : for (const auto& entry : mapCoinsByAddress) {
4128 3 : std::vector<COutput> vCoins, vRewardCoins;
4129 1 : bool maxSize = false;
4130 1 : vCoins = entry.second;
4131 :
4132 : // We don't want the tx to be refused for being too large
4133 : // we use 50 bytes as a base tx size (2 output: 2*34 + overhead: 10 -> 90 to be certain)
4134 1 : unsigned int txSizeEstimate = 90;
4135 :
4136 : //find masternode rewards that need to be combined
4137 1 : CCoinControl* coinControl = new CCoinControl();
4138 1 : CAmount nTotalRewardsValue = 0;
4139 3 : for (const COutput& out : vCoins) {
4140 3 : if (!out.fSpendable)
4141 0 : continue;
4142 :
4143 3 : COutPoint outpt(out.tx->GetHash(), out.i);
4144 3 : coinControl->Select(outpt);
4145 3 : vRewardCoins.push_back(out);
4146 3 : nTotalRewardsValue += out.Value();
4147 :
4148 : // Combine to the threshold and not way above considering the safety margin.
4149 3 : if ((nTotalRewardsValue - (nTotalRewardsValue / 10)) > nAutoCombineThreshold)
4150 : break;
4151 :
4152 : // Around 180 bytes per input. We use 190 to be certain
4153 2 : txSizeEstimate += 190;
4154 2 : if (txSizeEstimate >= MAX_STANDARD_TX_SIZE - 200) {
4155 : maxSize = true;
4156 : break;
4157 : }
4158 : }
4159 :
4160 : //if no inputs found then return
4161 1 : if (!coinControl->HasSelected())
4162 0 : continue;
4163 :
4164 : //we cannot combine one coin with itself
4165 1 : if (vRewardCoins.size() <= 1)
4166 0 : continue;
4167 :
4168 2 : std::vector<CRecipient> vecSend;
4169 2 : const CScript& scriptPubKey = GetScriptForDestination(entry.first);
4170 1 : vecSend.emplace_back(scriptPubKey, nTotalRewardsValue, false);
4171 :
4172 : //Send change to same address
4173 2 : CTxDestination destMyAddress;
4174 1 : if (!ExtractDestination(scriptPubKey, destMyAddress)) {
4175 0 : LogPrintf("AutoCombineDust: failed to extract destination\n");
4176 0 : continue;
4177 : }
4178 1 : coinControl->destChange = destMyAddress;
4179 :
4180 : // Create the transaction and commit it to the network
4181 1 : CTransactionRef wtx;
4182 2 : CReserveKey keyChange(this); // this change address does not end up being used, because change is returned with coin control switch
4183 2 : std::string strErr;
4184 1 : CAmount nFeeRet = 0;
4185 1 : int nChangePosInOut = -1;
4186 :
4187 : // 10% safety margin to avoid "Insufficient funds" errors
4188 1 : vecSend[0].nAmount = nTotalRewardsValue - (nTotalRewardsValue / 10);
4189 :
4190 1 : {
4191 : // For now, CreateTransaction requires cs_main lock.
4192 2 : LOCK2(cs_main, cs_wallet);
4193 1 : if (!CreateTransaction(vecSend, wtx, keyChange, nFeeRet, nChangePosInOut, strErr, coinControl,
4194 : true, false, CAmount(0))) {
4195 0 : LogPrintf("AutoCombineDust createtransaction failed, reason: %s\n", strErr);
4196 0 : continue;
4197 : }
4198 : }
4199 :
4200 : //we don't combine below the threshold unless the fees are 0 to avoid paying fees over fees over fees
4201 1 : if (!maxSize && vecSend[0].nAmount < nAutoCombineThreshold && nFeeRet > 0)
4202 0 : continue;
4203 :
4204 2 : const CWallet::CommitResult& res = CommitTransaction(wtx, keyChange, connman);
4205 1 : if (res.status != CWallet::CommitStatus::OK) {
4206 0 : LogPrintf("AutoCombineDust transaction commit failed\n");
4207 0 : continue;
4208 : }
4209 :
4210 1 : LogPrintf("AutoCombineDust sent transaction. Fee=%d, Total value=%d, Sending=%d\n", nFeeRet, nTotalRewardsValue, vecSend[0].nAmount);
4211 :
4212 2 : delete coinControl;
4213 : }
4214 : }
4215 :
4216 12 : void CWallet::LockOutpointIfMineWithMutex(const CTransactionRef& ptx, const COutPoint& c)
4217 : {
4218 36 : WITH_LOCK(cs_wallet, LockOutpointIfMine(ptx, c));
4219 12 : }
4220 :
4221 739 : void CWallet::LockOutpointIfMine(const CTransactionRef& ptx, const COutPoint& c)
4222 : {
4223 739 : AssertLockHeld(cs_wallet);
4224 739 : CTxOut txout;
4225 739 : if (ptx && c.hash == ptx->GetHash() && c.n < ptx->vout.size()) {
4226 : // the collateral is an output of this tx
4227 311 : txout = ptx->vout[c.n];
4228 : } else {
4229 : // the collateral is a reference to an utxo inside this wallet
4230 428 : const auto& it = mapWallet.find(c.hash);
4231 428 : if (it != mapWallet.end()) {
4232 554 : txout = it->second.tx->vout[c.n];
4233 : }
4234 : }
4235 739 : if (!txout.IsNull() && IsMine(txout) != ISMINE_NO && !IsSpent(c)) {
4236 154 : LockCoin(c);
4237 : }
4238 739 : }
4239 :
4240 : // Called from AddToWalletIfInvolvingMe
4241 647707 : void CWallet::LockIfMyCollateral(const CTransactionRef& ptx)
4242 : {
4243 647707 : AssertLockHeld(cs_wallet);
4244 :
4245 647707 : COutPoint o;
4246 647707 : if (GetProRegCollateral(ptx, o)) {
4247 727 : LockOutpointIfMine(ptx, o);
4248 : }
4249 647707 : }
4250 :
4251 363 : CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
4252 : {
4253 363 : const std::string& walletFile = name;
4254 :
4255 : // needed to restore wallet transaction meta data after -zapwallettxes
4256 363 : std::vector<CWalletTx> vWtx;
4257 :
4258 363 : if (gArgs.GetBoolArg("-zapwallettxes", false)) {
4259 5 : uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
4260 :
4261 10 : std::unique_ptr<CWallet> tempWallet = std::make_unique<CWallet>(name, WalletDatabase::Create(path));
4262 5 : DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
4263 5 : if (nZapWalletRet != DB_LOAD_OK) {
4264 0 : UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
4265 0 : return nullptr;
4266 : }
4267 : }
4268 :
4269 363 : uiInterface.InitMessage(_("Loading wallet..."));
4270 :
4271 363 : int64_t nStart = GetTimeMillis();
4272 363 : bool fFirstRun = true;
4273 726 : CWallet *walletInstance = new CWallet(name, WalletDatabase::Create(path));
4274 363 : DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
4275 362 : if (nLoadWalletRet != DB_LOAD_OK) {
4276 0 : if (nLoadWalletRet == DB_CORRUPT) {
4277 0 : UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
4278 0 : return nullptr;
4279 0 : } else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) {
4280 0 : UIWarning(strprintf(_("Warning: error reading %s! All keys read correctly, but transaction data"
4281 : " or address book entries might be missing or incorrect."), walletFile));
4282 0 : } else if (nLoadWalletRet == DB_TOO_NEW) {
4283 0 : UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME));
4284 0 : return nullptr;
4285 0 : } else if (nLoadWalletRet == DB_NEED_REWRITE) {
4286 0 : UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME));
4287 0 : return nullptr;
4288 : } else {
4289 0 : UIError(strprintf(_("Error loading %s\n"), walletFile));
4290 0 : return nullptr;
4291 : }
4292 : }
4293 :
4294 : // check minimum stake split threshold
4295 362 : if (walletInstance->nStakeSplitThreshold && walletInstance->nStakeSplitThreshold < CWallet::minStakeSplitThreshold) {
4296 0 : LogPrintf("WARNING: stake split threshold value %s too low. Restoring to minimum value %s.\n",
4297 0 : FormatMoney(walletInstance->nStakeSplitThreshold), FormatMoney(CWallet::minStakeSplitThreshold));
4298 0 : walletInstance->nStakeSplitThreshold = CWallet::minStakeSplitThreshold;
4299 : }
4300 :
4301 362 : int prev_version = walletInstance->GetVersion();
4302 :
4303 : // Forced upgrade
4304 362 : const bool fLegacyWallet = gArgs.GetBoolArg("-legacywallet", false);
4305 1045 : if (gArgs.GetBoolArg("-upgradewallet", fFirstRun && !fLegacyWallet) ||
4306 320 : (!walletInstance->IsLocked() && prev_version == FEATURE_PRE_SPLIT_KEYPOOL)) {
4307 202 : if (prev_version <= FEATURE_PRE_PIVX && walletInstance->IsLocked()) {
4308 : // Cannot upgrade a locked wallet
4309 0 : UIError(_("Cannot upgrade a locked wallet."));
4310 0 : return nullptr;
4311 : }
4312 :
4313 202 : int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
4314 202 : if (nMaxVersion == 0) // the -upgradewallet without argument case
4315 : {
4316 202 : LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
4317 202 : nMaxVersion = FEATURE_LATEST;
4318 202 : walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
4319 : } else {
4320 0 : LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
4321 : }
4322 202 : if (nMaxVersion < walletInstance->GetVersion()) {
4323 0 : UIError(_("Cannot downgrade wallet."));
4324 0 : return nullptr;
4325 : }
4326 202 : walletInstance->SetMaxVersion(nMaxVersion);
4327 : }
4328 :
4329 : // Upgrade to HD only if explicit upgrade was requested
4330 : // or if we are running an HD wallet and need to upgrade to Sapling.
4331 1085 : if (gArgs.GetBoolArg("-upgradewallet", false) ||
4332 722 : (!walletInstance->IsLocked() && prev_version == FEATURE_PRE_SPLIT_KEYPOOL)) {
4333 2 : std::string upgradeError;
4334 1 : if (!walletInstance->Upgrade(upgradeError, prev_version)) {
4335 0 : UIError(upgradeError);
4336 0 : return nullptr;
4337 : }
4338 : }
4339 :
4340 362 : if (fFirstRun) {
4341 201 : if (!fLegacyWallet) {
4342 : // Create new HD Wallet
4343 201 : LogPrintf("Creating HD Wallet\n");
4344 : // Ensure this wallet can only be opened by clients supporting HD.
4345 201 : walletInstance->SetMinVersion(FEATURE_LATEST);
4346 201 : walletInstance->SetupSPKM();
4347 : } else {
4348 0 : if (!Params().IsRegTestNet()) {
4349 0 : UIError("Legacy wallets can only be created on RegTest.");
4350 0 : return nullptr;
4351 : }
4352 : // Create legacy wallet
4353 0 : LogPrintf("Creating Pre-HD Wallet\n");
4354 0 : walletInstance->SetMaxVersion(FEATURE_PRE_PIVX);
4355 : }
4356 :
4357 : // Top up the keypool
4358 201 : if (!walletInstance->TopUpKeyPool()) {
4359 : // Error generating keys
4360 0 : UIError(_("Unable to generate initial key!"));
4361 0 : return nullptr;
4362 : }
4363 :
4364 804 : walletInstance->SetBestChain(WITH_LOCK(cs_main, return chainActive.GetLocator()));
4365 : }
4366 :
4367 363 : LogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
4368 :
4369 724 : LOCK(cs_main);
4370 362 : CBlockIndex* pindexRescan = chainActive.Genesis();
4371 :
4372 362 : if (gArgs.GetBoolArg("-rescan", false)) {
4373 : // clear note witness cache before a full rescan
4374 11 : walletInstance->ClearNoteWitnessCache();
4375 : } else {
4376 702 : WalletBatch batch(*walletInstance->database);
4377 702 : CBlockLocator locator;
4378 351 : if (batch.ReadBestBlock(locator))
4379 351 : pindexRescan = FindForkInGlobalIndex(chainActive, locator);
4380 : }
4381 :
4382 362 : {
4383 362 : LOCK(walletInstance->cs_wallet);
4384 528 : const CBlockIndex* tip = chainActive.Tip();
4385 166 : if (tip) {
4386 166 : walletInstance->m_last_block_processed = tip->GetBlockHash();
4387 166 : walletInstance->m_last_block_processed_height = tip->nHeight;
4388 166 : walletInstance->m_last_block_processed_time = tip->GetBlockTime();
4389 : }
4390 : }
4391 362 : RegisterValidationInterface(walletInstance);
4392 :
4393 488 : if (chainActive.Tip() && chainActive.Tip() != pindexRescan) {
4394 126 : uiInterface.InitMessage(_("Rescanning..."));
4395 126 : LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
4396 :
4397 : // no need to read and scan block, if block was created before
4398 : // our wallet birthday (as adjusted for block time variability)
4399 236 : while (pindexRescan && walletInstance->nTimeFirstKey &&
4400 236 : pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW)) {
4401 110 : pindexRescan = chainActive.Next(pindexRescan);
4402 : }
4403 126 : const int64_t nWalletRescanTime = GetTimeMillis();
4404 126 : {
4405 252 : WalletRescanReserver reserver(walletInstance);
4406 126 : if (!reserver.reserve()) {
4407 0 : UIError(_("Failed to rescan the wallet during initialization"));
4408 0 : return nullptr;
4409 : }
4410 126 : if (walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true, true) != nullptr) {
4411 0 : UIError(_("Shutdown requested over the txs scan. Exiting."));
4412 0 : return nullptr;
4413 : }
4414 : }
4415 126 : LogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nWalletRescanTime);
4416 126 : walletInstance->SetBestChain(chainActive.GetLocator());
4417 126 : walletInstance->database->IncrementUpdateCounter();
4418 :
4419 : // Restore wallet transaction metadata after -zapwallettxes=1
4420 143 : if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2") {
4421 6 : WalletBatch batch(*walletInstance->database);
4422 110 : for (const CWalletTx& wtxOld : vWtx) {
4423 107 : uint256 hash = wtxOld.GetHash();
4424 107 : std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
4425 107 : if (mi != walletInstance->mapWallet.end()) {
4426 105 : const CWalletTx* copyFrom = &wtxOld;
4427 105 : CWalletTx* copyTo = &mi->second;
4428 105 : copyTo->mapValue = copyFrom->mapValue;
4429 105 : copyTo->vOrderForm = copyFrom->vOrderForm;
4430 105 : copyTo->nTimeReceived = copyFrom->nTimeReceived;
4431 105 : copyTo->nTimeSmart = copyFrom->nTimeSmart;
4432 105 : copyTo->fFromMe = copyFrom->fFromMe;
4433 105 : copyTo->nOrderPos = copyFrom->nOrderPos;
4434 105 : batch.WriteTx(*copyTo);
4435 : }
4436 : }
4437 : }
4438 : }
4439 :
4440 : return walletInstance;
4441 : }
4442 :
4443 :
4444 : std::atomic<bool> CWallet::fFlushScheduled(false);
4445 :
4446 361 : void CWallet::postInitProcess(CScheduler& scheduler)
4447 : {
4448 : // Add wallet transactions that aren't already in a block to mapTransactions
4449 361 : ReacceptWalletTransactions(/*fFirstLoad*/true);
4450 :
4451 : // Run a thread to flush wallet periodically
4452 361 : if (!CWallet::fFlushScheduled.exchange(true)) {
4453 686 : scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
4454 : }
4455 361 : }
4456 :
4457 296 : bool CWallet::BackupWallet(const std::string& strDest)
4458 : {
4459 296 : return database->Backup(strDest);
4460 : }
4461 :
4462 9115 : CKeyPool::CKeyPool()
4463 : {
4464 9115 : nTime = GetTime();
4465 9115 : type = HDChain::ChangeType::EXTERNAL;
4466 9115 : m_pre_split = false;
4467 9115 : }
4468 :
4469 11506 : CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, const uint8_t& _type)
4470 : {
4471 11506 : nTime = GetTime();
4472 11506 : vchPubKey = vchPubKeyIn;
4473 11506 : type = _type;
4474 11506 : m_pre_split = false;
4475 11506 : }
4476 :
4477 16221668 : int CWalletTx::GetDepthInMainChain() const
4478 : {
4479 16221668 : assert(pwallet != nullptr);
4480 16221668 : AssertLockHeld(pwallet->cs_wallet);
4481 16221668 : if (isUnconfirmed() || isAbandoned()) return 0;
4482 :
4483 25617120 : return (pwallet->GetLastBlockHeight() - m_confirm.block_height + 1) * (isConflicted() ? -1 : 1);
4484 : }
4485 :
4486 4909335 : int CWalletTx::GetBlocksToMaturity() const
4487 : {
4488 8631050 : if (!(IsCoinBase() || IsCoinStake()))
4489 : return 0;
4490 2120733 : return std::max(0, (Params().GetConsensus().nCoinbaseMaturity + 1) - GetDepthInMainChain());
4491 : }
4492 :
4493 14062 : bool CWalletTx::IsInMainChainImmature() const
4494 : {
4495 18163 : if (!IsCoinBase() && !IsCoinStake()) return false;
4496 12271 : const int depth = GetDepthInMainChain();
4497 12271 : return (depth > 0 && depth <= Params().GetConsensus().nCoinbaseMaturity);
4498 : }
4499 :
4500 :
4501 1479 : bool CWalletTx::AcceptToMemoryPool(CValidationState& state)
4502 : {
4503 1479 : AssertLockHeld(cs_main);
4504 :
4505 : // Quick check to avoid re-setting fInMempool to false
4506 1479 : if (mempool.exists(tx->GetHash())) {
4507 : return false;
4508 : }
4509 :
4510 : // We must set fInMempool here - while it will be re-set to true by the
4511 : // entered-mempool callback, if we did not there would be a race where a
4512 : // user could call sendmoney in a loop and hit spurious out of funds errors
4513 : // because we think that the transaction they just generated's change is
4514 : // unavailable as we're not yet aware its in mempool.
4515 1472 : bool fMissingInputs;
4516 1472 : bool fAccepted = ::AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, false, true, false);
4517 1472 : fInMempool = fAccepted;
4518 1472 : if (!fAccepted) {
4519 35 : if (fMissingInputs) {
4520 : // For now, "missing inputs" error is not returning the proper state, so need to set it manually here.
4521 : // TODO: clean this setting the proper invalid state inside AcceptToMemoryPool (btc#15921).
4522 52 : state.Invalid(false, REJECT_INVALID, "Missing inputs");
4523 : }
4524 70 : LogPrintf("%s : %s\n", __func__, state.GetRejectReason());
4525 : }
4526 : return fAccepted;
4527 : }
4528 :
4529 361 : std::string CWallet::GetUniqueWalletBackupName() const
4530 : {
4531 361 : std::string name = !m_name.empty() ? SanitizeString(m_name, SAFE_CHARS_FILENAME) : "wallet_backup";
4532 724 : return strprintf("%s%s", name, FormatISO8601DateTimeForBackup(GetTime()));
4533 : }
4534 :
4535 1010 : CWallet::CWallet(std::string name, std::unique_ptr<WalletDatabase> database) : m_name(std::move(name)), database(std::move(database))
4536 : {
4537 505 : SetNull();
4538 505 : }
4539 :
4540 4406 : CWallet::~CWallet()
4541 : {
4542 504 : delete encrypted_batch;
4543 504 : delete pStakerStatus;
4544 876 : }
4545 :
4546 505 : void CWallet::SetNull()
4547 : {
4548 505 : nWalletVersion = FEATURE_BASE;
4549 505 : nWalletMaxVersion = FEATURE_BASE;
4550 505 : nMasterKeyMaxID = 0;
4551 505 : encrypted_batch = nullptr;
4552 505 : nOrderPosNext = 0;
4553 505 : nNextResend = 0;
4554 505 : nLastResend = 0;
4555 505 : nTimeFirstKey = 0;
4556 505 : nRelockTime = 0;
4557 505 : fAbortRescan = false;
4558 505 : fScanningWallet = false;
4559 505 : fWalletUnlockStaking = false;
4560 :
4561 : // Staker status (last hashed block and time)
4562 505 : if (pStakerStatus) {
4563 0 : pStakerStatus->SetNull();
4564 : } else {
4565 505 : pStakerStatus = new CStakerStatus();
4566 : }
4567 : // Stake split threshold
4568 505 : nStakeSplitThreshold = DEFAULT_STAKE_SPLIT_THRESHOLD;
4569 :
4570 : // User-defined fee PIV/kb
4571 505 : fUseCustomFee = false;
4572 505 : nCustomFee = CWallet::minTxFee.GetFeePerK();
4573 :
4574 : //Auto Combine Dust
4575 505 : fCombineDust = false;
4576 505 : nAutoCombineThreshold = 0;
4577 505 : frequency = 30;
4578 :
4579 : // Sapling.
4580 505 : m_sspk_man->nWitnessCacheSize = 0;
4581 505 : m_sspk_man->nWitnessCacheNeedsUpdate = true;
4582 505 : }
4583 :
4584 118580 : bool CWallet::CanSupportFeature(enum WalletFeature wf)
4585 : {
4586 118580 : AssertLockHeld(cs_wallet);
4587 118580 : return nWalletMaxVersion >= wf;
4588 : }
4589 :
4590 167 : bool CWallet::LoadMinVersion(int nVersion)
4591 : {
4592 167 : AssertLockHeld(cs_wallet);
4593 167 : nWalletVersion = nVersion;
4594 167 : nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion);
4595 167 : return true;
4596 : }
4597 :
4598 6242023 : isminetype CWallet::IsMine(const CTxOut& txout) const
4599 : {
4600 6242023 : return ::IsMine(*this, txout.scriptPubKey);
4601 : }
4602 :
4603 179777 : CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
4604 : {
4605 179777 : if (!Params().GetConsensus().MoneyRange(txout.nValue))
4606 0 : throw std::runtime_error("CWallet::GetCredit() : value out of range");
4607 179777 : return ((IsMine(txout) & filter) ? txout.nValue : 0);
4608 : }
4609 :
4610 0 : CAmount CWallet::GetChange(const CTxOut& txout) const
4611 : {
4612 0 : if (!Params().GetConsensus().MoneyRange(txout.nValue))
4613 0 : throw std::runtime_error("CWallet::GetChange() : value out of range");
4614 0 : return (IsChange(txout) ? txout.nValue : 0);
4615 : }
4616 :
4617 370355 : bool CWallet::IsMine(const CTransactionRef& tx) const
4618 : {
4619 943689 : for (const CTxOut& txout : tx->vout)
4620 690939 : if (IsMine(txout))
4621 117605 : return true;
4622 252750 : return false;
4623 : }
4624 :
4625 647709 : bool CWallet::IsFromMe(const CTransactionRef& tx) const
4626 : {
4627 647709 : if (GetDebit(tx, ISMINE_ALL) > 0) {
4628 : return true;
4629 : }
4630 :
4631 273970 : if (tx->IsShieldedTx()) {
4632 2132 : for (const SpendDescription& spend : tx->sapData->vShieldedSpend) {
4633 191 : if (m_sspk_man->IsSaplingNullifierFromMe(spend.nullifier)) {
4634 0 : return true;
4635 : }
4636 : }
4637 : }
4638 :
4639 : return false;
4640 : }
4641 :
4642 671398 : CAmount CWallet::GetDebit(const CTransactionRef& tx, const isminefilter& filter) const
4643 : {
4644 671398 : CAmount nDebit = 0;
4645 1858368 : for (const CTxIn& txin : tx->vin) {
4646 1186966 : nDebit += GetDebit(txin, filter);
4647 2373932 : if (!Params().GetConsensus().MoneyRange(nDebit))
4648 0 : throw std::runtime_error("CWallet::GetDebit() : value out of range");
4649 : }
4650 :
4651 : // Shielded debit
4652 671398 : if (filter & ISMINE_SPENDABLE_SHIELDED || filter & ISMINE_WATCH_ONLY_SHIELDED) {
4653 652403 : if (tx->hasSaplingData()) {
4654 4786 : nDebit += m_sspk_man->GetDebit(*tx, filter);
4655 : }
4656 : }
4657 :
4658 671398 : return nDebit;
4659 : }
4660 :
4661 6319 : CAmount CWallet::GetCredit(const CWalletTx& tx, const isminefilter& filter) const
4662 : {
4663 6319 : CAmount nCredit = 0;
4664 13750 : for (unsigned int i = 0; i < tx.tx->vout.size(); i++) {
4665 7431 : nCredit += GetCredit(tx.tx->vout[i], filter);
4666 : }
4667 :
4668 : // Shielded credit
4669 6319 : if (filter & ISMINE_SPENDABLE_SHIELDED || filter & ISMINE_WATCH_ONLY_SHIELDED) {
4670 2144 : if (tx.tx->hasSaplingData()) {
4671 10 : nCredit += m_sspk_man->GetCredit(tx, filter, false);
4672 : }
4673 : }
4674 :
4675 6319 : if (!Params().GetConsensus().MoneyRange(nCredit))
4676 0 : throw std::runtime_error("CWallet::GetCredit() : value out of range");
4677 6319 : return nCredit;
4678 : }
4679 :
4680 0 : CAmount CWallet::GetChange(const CTransactionRef& tx) const
4681 : {
4682 0 : CAmount nChange = 0;
4683 0 : for (const CTxOut& txout : tx->vout) {
4684 0 : nChange += GetChange(txout);
4685 0 : if (!Params().GetConsensus().MoneyRange(nChange))
4686 0 : throw std::runtime_error("CWallet::GetChange() : value out of range");
4687 : }
4688 0 : return nChange;
4689 : }
4690 :
4691 434 : unsigned int CWallet::GetKeyPoolSize()
4692 : {
4693 434 : return m_spk_man->GetKeyPoolSize();
4694 : }
4695 :
4696 65 : unsigned int CWallet::GetStakingKeyPoolSize()
4697 : {
4698 65 : return m_spk_man->GetStakingKeyPoolSize();
4699 : }
4700 :
4701 868 : int CWallet::GetVersion()
4702 : {
4703 868 : LOCK(cs_wallet);
4704 868 : return nWalletVersion;
4705 : }
4706 :
4707 : ///////////////// Sapling Methods //////////////////////////
4708 : ////////////////////////////////////////////////////////////
4709 :
4710 1246 : libzcash::SaplingPaymentAddress CWallet::GenerateNewSaplingZKey(std::string label) {
4711 1246 : if (!m_sspk_man->IsEnabled()) {
4712 1 : throw std::runtime_error("Cannot generate shielded addresses. Start with -upgradewallet in order to upgrade a non-HD wallet to HD and Sapling features");
4713 : }
4714 :
4715 1245 : auto address = m_sspk_man->GenerateNewSaplingZKey();
4716 1244 : SetAddressBook(address, label, AddressBook::AddressBookPurpose::SHIELDED_RECEIVE);
4717 1244 : return address;
4718 : }
4719 :
4720 42368 : void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
4721 : const CBlock* pblock,
4722 42368 : SaplingMerkleTree& saplingTree) { m_sspk_man->IncrementNoteWitnesses(pindex, pblock, saplingTree); }
4723 :
4724 5 : void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) { m_sspk_man->DecrementNoteWitnesses(pindex); }
4725 :
4726 11 : void CWallet::ClearNoteWitnessCache() { m_sspk_man->ClearNoteWitnessCache(); }
4727 :
4728 1020 : bool CWallet::AddSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key) { return m_sspk_man->AddSaplingZKey(key); }
4729 :
4730 1 : bool CWallet::AddSaplingIncomingViewingKeyW(
4731 : const libzcash::SaplingIncomingViewingKey &ivk,
4732 1 : const libzcash::SaplingPaymentAddress &addr) { return m_sspk_man->AddSaplingIncomingViewingKey(ivk, addr); }
4733 :
4734 0 : bool CWallet::AddCryptedSaplingSpendingKeyW(
4735 : const libzcash::SaplingExtendedFullViewingKey &extfvk,
4736 0 : const std::vector<unsigned char> &vchCryptedSecret) { return m_sspk_man->AddCryptedSaplingSpendingKeyDB(extfvk, vchCryptedSecret); }
4737 :
4738 3692 : bool CWallet::HaveSpendingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &zaddr) const { return m_sspk_man->HaveSpendingKeyForPaymentAddress(zaddr); }
4739 36 : bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key) { return m_sspk_man->LoadSaplingZKey(key); }
4740 38 : bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta) { return m_sspk_man->LoadSaplingZKeyMetadata(ivk, meta); }
4741 2 : bool CWallet::LoadCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
4742 2 : const std::vector<unsigned char> &vchCryptedSecret) { return m_sspk_man->LoadCryptedSaplingZKey(extfvk, vchCryptedSecret); }
4743 :
4744 1 : bool CWallet::LoadSaplingPaymentAddress(
4745 : const libzcash::SaplingPaymentAddress &addr,
4746 1 : const libzcash::SaplingIncomingViewingKey &ivk) { return m_sspk_man->LoadSaplingPaymentAddress(addr, ivk); }
4747 :
4748 : ///////////////// End Sapling Methods //////////////////////
4749 : ////////////////////////////////////////////////////////////
4750 :
4751 757450 : CWalletTx::CWalletTx(const CWallet* pwalletIn, CTransactionRef arg)
4752 3787240 : : tx(std::move(arg))
4753 : {
4754 757450 : Init(pwalletIn);
4755 757450 : }
4756 :
4757 764213 : void CWalletTx::Init(const CWallet* pwalletIn)
4758 : {
4759 764213 : pwallet = pwalletIn;
4760 764213 : mapValue.clear();
4761 764213 : mapSaplingNoteData.clear();
4762 764213 : vOrderForm.clear();
4763 764213 : fTimeReceivedIsTxTime = false;
4764 764213 : nTimeReceived = 0;
4765 764213 : nTimeSmart = 0;
4766 764213 : fFromMe = false;
4767 764213 : fChangeCached = false;
4768 764213 : fInMempool = false;
4769 764213 : nChangeCached = 0;
4770 764213 : fStakeDelegationVoided = false;
4771 764213 : fShieldedChangeCached = false;
4772 764213 : nShieldedChangeCached = 0;
4773 764213 : nOrderPos = -1;
4774 764213 : m_confirm = Confirmation{};
4775 764213 : }
4776 :
4777 4493103 : bool CWalletTx::IsTrusted() const
4778 : {
4779 4493103 : bool fConflicted = false;
4780 4493103 : int nDepth = 0;
4781 4493103 : return IsTrusted(nDepth, fConflicted);
4782 : }
4783 :
4784 4540030 : bool CWalletTx::IsTrusted(int& nDepth, bool& fConflicted) const
4785 : {
4786 4540030 : {
4787 4540030 : LOCK(pwallet->cs_wallet); // future: receive block height instead of locking here.
4788 : // Quick answer in most cases
4789 4540030 : if (!IsFinalTx(tx, pwallet->GetLastBlockHeight()))
4790 0 : return false;
4791 : }
4792 :
4793 4540030 : nDepth = GetDepthAndMempool(fConflicted);
4794 :
4795 4540030 : if (fConflicted) // Don't trust unconfirmed transactions from us unless they are in the mempool.
4796 : return false;
4797 4427201 : if (nDepth >= 1)
4798 : return true;
4799 1002048 : if (nDepth < 0)
4800 : return false;
4801 1001838 : if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
4802 16 : return false;
4803 :
4804 : // Trusted if all inputs are from us and are in the mempool:
4805 2004134 : for (const CTxIn& txin : tx->vin) {
4806 : // Transactions not sent by us: not trusted
4807 1002317 : const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
4808 1002317 : if (parent == nullptr)
4809 0 : return false;
4810 1002317 : const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
4811 1002317 : if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
4812 : return false;
4813 : }
4814 1001817 : return true;
4815 : }
4816 :
4817 10280524 : int CWalletTx::GetDepthAndMempool(bool& fConflicted) const
4818 : {
4819 10280524 : int ret = GetDepthInMainChain();
4820 10280524 : fConflicted = (ret == 0 && !InMempool()); // not in chain nor in mempool
4821 10280524 : return ret;
4822 : }
4823 :
4824 0 : bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
4825 : {
4826 0 : CMutableTransaction tx1 {*tx};
4827 0 : CMutableTransaction tx2 {*_tx.tx};
4828 0 : for (auto& txin : tx1.vin) txin.scriptSig = CScript();
4829 0 : for (auto& txin : tx2.vin) txin.scriptSig = CScript();
4830 0 : return CTransaction(tx1) == CTransaction(tx2);
4831 : }
4832 :
4833 1544786 : void CWalletTx::MarkDirty()
4834 : {
4835 1544786 : m_amounts[DEBIT].Reset();
4836 1544786 : m_amounts[CREDIT].Reset();
4837 1544786 : m_amounts[IMMATURE_CREDIT].Reset();
4838 1544786 : m_amounts[AVAILABLE_CREDIT].Reset();
4839 1544786 : nChangeCached = 0;
4840 1544786 : fChangeCached = false;
4841 1544786 : nShieldedChangeCached = 0;
4842 1544786 : fShieldedChangeCached = false;
4843 1544786 : fStakeDelegationVoided = false;
4844 1544786 : }
4845 :
4846 406244 : void CWalletTx::BindWallet(CWallet* pwalletIn)
4847 : {
4848 406244 : pwallet = pwalletIn;
4849 406244 : MarkDirty();
4850 406244 : }
4851 :
4852 2030 : void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData)
4853 : {
4854 2030 : mapSaplingNoteData.clear();
4855 4203 : for (const std::pair<SaplingOutPoint, SaplingNoteData> nd : noteData) {
4856 2174 : if (nd.first.n < tx->sapData->vShieldedOutput.size()) {
4857 2173 : mapSaplingNoteData[nd.first] = nd.second;
4858 : } else {
4859 1 : throw std::logic_error("CWalletTx::SetSaplingNoteData(): Invalid note");
4860 : }
4861 : }
4862 2029 : }
4863 :
4864 : Optional<std::pair<
4865 : libzcash::SaplingNotePlaintext,
4866 1175 : libzcash::SaplingPaymentAddress>> CWalletTx::DecryptSaplingNote(const SaplingOutPoint& op) const
4867 : {
4868 : // Check whether we can decrypt this SaplingOutPoint with the ivk
4869 1175 : auto it = this->mapSaplingNoteData.find(op);
4870 1175 : if (it == this->mapSaplingNoteData.end() || !it->second.IsMyNote()) {
4871 0 : return nullopt;
4872 : }
4873 :
4874 1175 : auto output = this->tx->sapData->vShieldedOutput[op.n];
4875 2350 : auto nd = this->mapSaplingNoteData.at(op);
4876 :
4877 1175 : auto maybe_pt = libzcash::SaplingNotePlaintext::decrypt(
4878 : output.encCiphertext,
4879 1175 : *(nd.ivk),
4880 : output.ephemeralKey,
4881 1175 : output.cmu);
4882 1175 : assert(static_cast<bool>(maybe_pt));
4883 1175 : auto notePt = maybe_pt.get();
4884 :
4885 2350 : auto maybe_pa = nd.ivk->address(notePt.d);
4886 1175 : assert(static_cast<bool>(maybe_pa));
4887 1175 : auto pa = maybe_pa.get();
4888 :
4889 1175 : return std::make_pair(notePt, pa);
4890 : }
4891 :
4892 : Optional<std::pair<
4893 : libzcash::SaplingNotePlaintext,
4894 99 : libzcash::SaplingPaymentAddress>> CWalletTx::RecoverSaplingNote(const SaplingOutPoint& op, const std::set<uint256>& ovks) const
4895 : {
4896 99 : auto output = this->tx->sapData->vShieldedOutput[op.n];
4897 :
4898 107 : for (const auto& ovk : ovks) {
4899 103 : auto outPt = libzcash::SaplingOutgoingPlaintext::decrypt(
4900 : output.outCiphertext,
4901 : ovk,
4902 : output.cv,
4903 : output.cmu,
4904 103 : output.ephemeralKey);
4905 103 : if (!outPt) {
4906 8 : continue;
4907 : }
4908 :
4909 95 : auto maybe_pt = libzcash::SaplingNotePlaintext::decrypt(
4910 : output.encCiphertext,
4911 : output.ephemeralKey,
4912 95 : outPt->esk,
4913 95 : outPt->pk_d,
4914 190 : output.cmu);
4915 95 : assert(static_cast<bool>(maybe_pt));
4916 95 : auto notePt = maybe_pt.get();
4917 :
4918 95 : return std::make_pair(notePt, libzcash::SaplingPaymentAddress(notePt.d, outPt->pk_d));
4919 : }
4920 :
4921 : // Couldn't recover with any of the provided OutgoingViewingKeys
4922 4 : return nullopt;
4923 : }
4924 :
4925 0 : bool CWalletTx::HasP2CSInputs() const
4926 : {
4927 0 : return GetStakeDelegationDebit(true) > 0 || GetColdStakingDebit(true) > 0;
4928 : }
4929 :
4930 0 : CAmount CWalletTx::GetChange() const
4931 : {
4932 0 : if (fChangeCached)
4933 0 : return nChangeCached;
4934 0 : nChangeCached = pwallet->GetChange(tx);
4935 0 : fChangeCached = true;
4936 0 : return nChangeCached;
4937 : }
4938 :
4939 3 : CAmount CWalletTx::GetShieldedChange() const
4940 : {
4941 3 : if (fShieldedChangeCached) {
4942 0 : return nShieldedChangeCached;
4943 : }
4944 3 : nShieldedChangeCached = pwallet->GetSaplingScriptPubKeyMan()->GetShieldedChange(*this);
4945 3 : fShieldedChangeCached = true;
4946 3 : return nShieldedChangeCached;
4947 : }
4948 :
4949 1519126 : bool CWalletTx::IsFromMe(const isminefilter& filter) const
4950 : {
4951 1519126 : return (GetDebit(filter) > 0);
4952 : }
4953 :
4954 3 : CAmount CWalletTx::GetShieldedAvailableCredit(bool fUseCache) const
4955 : {
4956 3 : return GetAvailableCredit(fUseCache, ISMINE_SPENDABLE_SHIELDED);
4957 : }
4958 :
4959 253 : const CTxDestination* CAddressBookIterator::GetCTxDestKey()
4960 : {
4961 253 : return boost::get<CTxDestination>(&it->first);
4962 : }
4963 :
4964 34 : const libzcash::SaplingPaymentAddress* CAddressBookIterator::GetShieldedDestKey()
4965 : {
4966 34 : return boost::get<libzcash::SaplingPaymentAddress>(&it->first);
4967 : }
4968 :
4969 0 : const CWDestination* CAddressBookIterator::GetDestKey()
4970 : {
4971 0 : return &it->first;
4972 : }
4973 :
4974 328438 : CStakeableOutput::CStakeableOutput(const CWalletTx* txIn,
4975 : int iIn,
4976 : int nDepthIn,
4977 328438 : const CBlockIndex*& _pindex) :
4978 : COutput(txIn, iIn, nDepthIn, true /*fSpendable*/, true/*fSolvable*/, true/*fSafe*/),
4979 328438 : pindex(_pindex)
4980 328438 : {}
|