]> Git Repo - VerusCoin.git/blame - src/wallet/wallet.cpp
test
[VerusCoin.git] / src / wallet / wallet.cpp
CommitLineData
b2120e22 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
5b40d886 3// Distributed under the MIT software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
e8ef3da7 5
50c72f23 6#include "wallet/wallet.h"
51ed9ec9 7
10254401 8#include "base58.h"
3e1cf9b6 9#include "checkpoints.h"
6a86c24d 10#include "coincontrol.h"
da29ecbc 11#include "consensus/validation.h"
02e67455 12#include "init.h"
8a893c94 13#include "main.h"
0689f46c 14#include "net.h"
e088d65a 15#include "script/script.h"
16#include "script/sign.h"
14f888ca 17#include "timedata.h"
ad49c256 18#include "utilmoneystr.h"
02e67455 19#include "zcash/Note.hpp"
73699cea 20#include "crypter.h"
4a4e912b 21#include "coins.h"
d0c4197e
PK
22#include <assert.h>
23
cae686d3 24#include <boost/algorithm/string/replace.hpp>
2bb1c877 25#include <boost/filesystem.hpp>
ad49c256 26#include <boost/thread.hpp>
e8ef3da7
WL
27
28using namespace std;
c1c45943 29using namespace libzcash;
e8ef3da7 30
5b40d886
MF
31/**
32 * Settings
33 */
c6cb21d1 34CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
aa279d61 35CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
77ed59df 36unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
1bbca249 37bool bSpendZeroConfChange = true;
c1c9d5b4 38bool fSendFreeTransactions = false;
ed3e5e46 39bool fPayAtLeastCustomFee = true;
6ad13d7c 40extern int32_t KOMODO_EXCHANGEWALLET;
e8ef3da7 41
7e6d23b1
CD
42/**
43 * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
5b40d886
MF
44 * Override with -mintxfee
45 */
9b1627d1 46CFeeRate CWallet::minTxFee = CFeeRate(1000);
13fc83c7 47
5b40d886
MF
48/** @defgroup mapWallet
49 *
50 * @{
51 */
e8ef3da7 52
d650f96d
CM
53struct CompareValueOnly
54{
a372168e
MF
55 bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
56 const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
d650f96d
CM
57 {
58 return t1.first < t2.first;
59 }
60};
61
02e67455
JG
62std::string JSOutPoint::ToString() const
63{
64 return strprintf("JSOutPoint(%s, %d, %d)", hash.ToString().substr(0,10), js, n);
65}
66
ad49c256
WL
67std::string COutput::ToString() const
68{
805344dc 69 return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
ad49c256
WL
70}
71
93a18a36
GA
72const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
73{
74 LOCK(cs_wallet);
75 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
76 if (it == mapWallet.end())
77 return NULL;
78 return &(it->second);
79}
80
c1c45943
S
81// Generate a new spending key and return its public payment address
82CZCPaymentAddress CWallet::GenerateNewZKey()
83{
84 AssertLockHeld(cs_wallet); // mapZKeyMetadata
85 auto k = SpendingKey::random();
86 auto addr = k.address();
87
88 // Check for collision, even though it is unlikely to ever occur
89 if (CCryptoKeyStore::HaveSpendingKey(addr))
0feffd14 90 throw std::runtime_error("CWallet::GenerateNewZKey(): Collision detected");
c1c45943
S
91
92 // Create new metadata
93 int64_t nCreationTime = GetTime();
94 mapZKeyMetadata[addr] = CKeyMetadata(nCreationTime);
95
96 CZCPaymentAddress pubaddr(addr);
97 if (!AddZKey(k))
0feffd14 98 throw std::runtime_error("CWallet::GenerateNewZKey(): AddZKey failed");
c1c45943
S
99 return pubaddr;
100}
101
102// Add spending key to keystore and persist to disk
103bool CWallet::AddZKey(const libzcash::SpendingKey &key)
104{
105 AssertLockHeld(cs_wallet); // mapZKeyMetadata
106 auto addr = key.address();
107
108 if (!CCryptoKeyStore::AddSpendingKey(key))
109 return false;
110
111 if (!fFileBacked)
112 return true;
113
114 if (!IsCrypted()) {
115 return CWalletDB(strWalletFile).WriteZKey(addr,
116 key,
117 mapZKeyMetadata[addr]);
118 }
119 return true;
120}
121
fd61d6f5 122CPubKey CWallet::GenerateNewKey()
9976cf07 123{
95691680 124 AssertLockHeld(cs_wallet); // mapKeyMetadata
439e1497 125 bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
38067c18 126
dfa23b94
PW
127 CKey secret;
128 secret.MakeNewKey(fCompressed);
38067c18
PW
129
130 // Compressed public keys were introduced in version 0.6.0
131 if (fCompressed)
439e1497 132 SetMinVersion(FEATURE_COMPRPUBKEY);
38067c18 133
dfa23b94 134 CPubKey pubkey = secret.GetPubKey();
d0c41a73 135 assert(secret.VerifyPubKey(pubkey));
4addb2c0
PW
136
137 // Create new metadata
51ed9ec9 138 int64_t nCreationTime = GetTime();
4addb2c0
PW
139 mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
140 if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
141 nTimeFirstKey = nCreationTime;
142
dfa23b94 143 if (!AddKeyPubKey(secret, pubkey))
5262fde0 144 throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
dfa23b94 145 return pubkey;
9976cf07 146}
e8ef3da7 147
4addb2c0 148bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
e8ef3da7 149{
95691680 150 AssertLockHeld(cs_wallet); // mapKeyMetadata
dfa23b94 151 if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
acd65016 152 return false;
ccca27a7
CL
153
154 // check if we need to remove from watch-only
155 CScript script;
156 script = GetScriptForDestination(pubkey.GetID());
157 if (HaveWatchOnly(script))
158 RemoveWatchOnly(script);
159
e8ef3da7
WL
160 if (!fFileBacked)
161 return true;
dfa23b94 162 if (!IsCrypted()) {
3869fb89
JG
163 return CWalletDB(strWalletFile).WriteKey(pubkey,
164 secret.GetPrivKey(),
4addb2c0 165 mapKeyMetadata[pubkey.GetID()]);
dfa23b94 166 }
84c3c2eb 167 return true;
4e87d341
MC
168}
169
3869fb89 170bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
4addb2c0 171 const vector<unsigned char> &vchCryptedSecret)
4e87d341 172{
73699cea 173
4e87d341
MC
174 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
175 return false;
176 if (!fFileBacked)
177 return true;
96f34cd5 178 {
f8dcd5ca 179 LOCK(cs_wallet);
96f34cd5 180 if (pwalletdbEncryption)
3869fb89
JG
181 return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
182 vchCryptedSecret,
4addb2c0 183 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 184 else
3869fb89
JG
185 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
186 vchCryptedSecret,
4addb2c0 187 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 188 }
0767e691 189 return false;
4e87d341
MC
190}
191
73699cea
S
192
193bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
2aa9c025 194 const libzcash::ViewingKey &vk,
73699cea
S
195 const std::vector<unsigned char> &vchCryptedSecret)
196{
2aa9c025 197 if (!CCryptoKeyStore::AddCryptedSpendingKey(address, vk, vchCryptedSecret))
73699cea
S
198 return false;
199 if (!fFileBacked)
200 return true;
201 {
202 LOCK(cs_wallet);
82bd9ee8 203 if (pwalletdbEncryption) {
73699cea 204 return pwalletdbEncryption->WriteCryptedZKey(address,
2aa9c025 205 vk,
73699cea
S
206 vchCryptedSecret,
207 mapZKeyMetadata[address]);
82bd9ee8 208 } else {
73699cea 209 return CWalletDB(strWalletFile).WriteCryptedZKey(address,
2aa9c025 210 vk,
73699cea
S
211 vchCryptedSecret,
212 mapZKeyMetadata[address]);
82bd9ee8 213 }
73699cea
S
214 }
215 return false;
216}
217
4addb2c0
PW
218bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
219{
95691680 220 AssertLockHeld(cs_wallet); // mapKeyMetadata
4addb2c0
PW
221 if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
222 nTimeFirstKey = meta.nCreateTime;
223
224 mapKeyMetadata[pubkey.GetID()] = meta;
225 return true;
226}
227
c1c45943
S
228bool CWallet::LoadZKeyMetadata(const PaymentAddress &addr, const CKeyMetadata &meta)
229{
230 AssertLockHeld(cs_wallet); // mapZKeyMetadata
231 mapZKeyMetadata[addr] = meta;
232 return true;
233}
234
2f15e86a
GA
235bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
236{
237 return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
238}
239
2aa9c025 240bool CWallet::LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret)
73699cea 241{
2aa9c025 242 return CCryptoKeyStore::AddCryptedSpendingKey(addr, vk, vchCryptedSecret);
73699cea
S
243}
244
c1c45943
S
245bool CWallet::LoadZKey(const libzcash::SpendingKey &key)
246{
247 return CCryptoKeyStore::AddSpendingKey(key);
248}
249
922e8e29 250bool CWallet::AddCScript(const CScript& redeemScript)
e679ec96 251{
922e8e29 252 if (!CCryptoKeyStore::AddCScript(redeemScript))
e679ec96
GA
253 return false;
254 if (!fFileBacked)
255 return true;
922e8e29 256 return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
e679ec96
GA
257}
258
18116b06
WL
259bool CWallet::LoadCScript(const CScript& redeemScript)
260{
261 /* A sanity check was added in pull #3843 to avoid adding redeemScripts
262 * that never can be redeemed. However, old wallets may still contain
263 * these. Do not add them to the wallet and warn. */
264 if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
265 {
066e2a14 266 std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString();
18116b06
WL
267 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",
268 __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
269 return true;
270 }
271
272 return CCryptoKeyStore::AddCScript(redeemScript);
273}
274
d5087d1b 275bool CWallet::AddWatchOnly(const CScript &dest)
c8988460
PW
276{
277 if (!CCryptoKeyStore::AddWatchOnly(dest))
278 return false;
279 nTimeFirstKey = 1; // No birthday information for watch-only keys.
939ed973 280 NotifyWatchonlyChanged(true);
c8988460
PW
281 if (!fFileBacked)
282 return true;
283 return CWalletDB(strWalletFile).WriteWatchOnly(dest);
284}
285
ccca27a7
CL
286bool CWallet::RemoveWatchOnly(const CScript &dest)
287{
288 AssertLockHeld(cs_wallet);
289 if (!CCryptoKeyStore::RemoveWatchOnly(dest))
290 return false;
291 if (!HaveWatchOnly())
292 NotifyWatchonlyChanged(false);
293 if (fFileBacked)
294 if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
295 return false;
296
297 return true;
298}
299
d5087d1b 300bool CWallet::LoadWatchOnly(const CScript &dest)
c8988460 301{
c8988460
PW
302 return CCryptoKeyStore::AddWatchOnly(dest);
303}
304
94f778bd 305bool CWallet::Unlock(const SecureString& strWalletPassphrase)
4e87d341 306{
6cc4a62c
GA
307 CCrypter crypter;
308 CKeyingMaterial vMasterKey;
4e87d341 309
f8dcd5ca
PW
310 {
311 LOCK(cs_wallet);
4e87d341
MC
312 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
313 {
314 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
315 return false;
316 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
92f2c1fe 317 continue; // try another master key
4e87d341
MC
318 if (CCryptoKeyStore::Unlock(vMasterKey))
319 return true;
320 }
f8dcd5ca 321 }
4e87d341
MC
322 return false;
323}
324
94f778bd 325bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
4e87d341 326{
6cc4a62c 327 bool fWasLocked = IsLocked();
4e87d341 328
6cc4a62c 329 {
f8dcd5ca 330 LOCK(cs_wallet);
4e87d341
MC
331 Lock();
332
333 CCrypter crypter;
334 CKeyingMaterial vMasterKey;
335 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
336 {
337 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
338 return false;
6cc4a62c 339 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
4e87d341
MC
340 return false;
341 if (CCryptoKeyStore::Unlock(vMasterKey))
342 {
51ed9ec9 343 int64_t nStartTime = GetTimeMillis();
ddebdd9a
MC
344 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
345 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
346
347 nStartTime = GetTimeMillis();
348 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
349 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
350
351 if (pMasterKey.second.nDeriveIterations < 25000)
352 pMasterKey.second.nDeriveIterations = 25000;
353
881a85a2 354 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
ddebdd9a 355
4e87d341
MC
356 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
357 return false;
358 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
359 return false;
360 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
361 if (fWasLocked)
362 Lock();
363 return true;
364 }
365 }
366 }
6cc4a62c 367
4e87d341
MC
368 return false;
369}
370
de42390f
JG
371void CWallet::ChainTip(const CBlockIndex *pindex, const CBlock *pblock,
372 ZCIncrementalMerkleTree tree, bool added)
769e031c
JG
373{
374 if (added) {
de42390f 375 IncrementNoteWitnesses(pindex, pblock, tree);
769e031c 376 } else {
40ef121e 377 DecrementNoteWitnesses(pindex);
769e031c
JG
378 }
379}
380
ed6d0b5f
PW
381void CWallet::SetBestChain(const CBlockLocator& loc)
382{
383 CWalletDB walletdb(strWalletFile);
03f83b9b 384 SetBestChainINTERNAL(walletdb, loc);
ed6d0b5f 385}
7414733b 386
439e1497 387bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
0b807a41 388{
ca4cf5cf 389 LOCK(cs_wallet); // nWalletVersion
0b807a41
PW
390 if (nWalletVersion >= nVersion)
391 return true;
392
439e1497
PW
393 // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
394 if (fExplicit && nVersion > nWalletMaxVersion)
395 nVersion = FEATURE_LATEST;
396
0b807a41
PW
397 nWalletVersion = nVersion;
398
439e1497
PW
399 if (nVersion > nWalletMaxVersion)
400 nWalletMaxVersion = nVersion;
401
0b807a41
PW
402 if (fFileBacked)
403 {
404 CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
0b807a41
PW
405 if (nWalletVersion > 40000)
406 pwalletdb->WriteMinVersion(nWalletVersion);
407 if (!pwalletdbIn)
408 delete pwalletdb;
409 }
410
411 return true;
412}
413
439e1497
PW
414bool CWallet::SetMaxVersion(int nVersion)
415{
ca4cf5cf 416 LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
439e1497
PW
417 // cannot downgrade below current version
418 if (nWalletVersion > nVersion)
419 return false;
420
421 nWalletMaxVersion = nVersion;
422
423 return true;
424}
425
3015e0bc 426set<uint256> CWallet::GetConflicts(const uint256& txid) const
731b89b8
GA
427{
428 set<uint256> result;
429 AssertLockHeld(cs_wallet);
430
431 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
432 if (it == mapWallet.end())
433 return result;
434 const CWalletTx& wtx = it->second;
435
93a18a36 436 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
731b89b8
GA
437
438 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
439 {
93a18a36
GA
440 if (mapTxSpends.count(txin.prevout) <= 1)
441 continue; // No conflict if zero or one spends
442 range = mapTxSpends.equal_range(txin.prevout);
443 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
3015e0bc 444 result.insert(it->second);
731b89b8 445 }
0f106047
JG
446
447 std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
448
449 for (const JSDescription& jsdesc : wtx.vjoinsplit) {
450 for (const uint256& nullifier : jsdesc.nullifiers) {
451 if (mapTxNullifiers.count(nullifier) <= 1) {
452 continue; // No conflict if zero or one spends
453 }
454 range_n = mapTxNullifiers.equal_range(nullifier);
455 for (TxNullifiers::const_iterator it = range_n.first; it != range_n.second; ++it) {
456 result.insert(it->second);
457 }
458 }
459 }
731b89b8
GA
460 return result;
461}
462
2bb1c877
JS
463void CWallet::Flush(bool shutdown)
464{
465 bitdb.Flush(shutdown);
466}
467
341e2385 468bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
2bb1c877
JS
469{
470 if (!bitdb.Open(GetDataDir()))
471 {
472 // try moving the database env out of the way
473 boost::filesystem::path pathDatabase = GetDataDir() / "database";
474 boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%d.bak", GetTime());
475 try {
476 boost::filesystem::rename(pathDatabase, pathDatabaseBak);
477 LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string());
478 } catch (const boost::filesystem::filesystem_error&) {
479 // failure is ok (well, not really, but it's not worse than what we started with)
480 }
481
482 // try again
483 if (!bitdb.Open(GetDataDir())) {
484 // if it still fails, it probably means we can't even create the database env
485 string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
486 errorString += msg;
487 return true;
488 }
489 }
490
491 if (GetBoolArg("-salvagewallet", false))
492 {
493 // Recover readable keypairs:
494 if (!CWalletDB::Recover(bitdb, walletFile, true))
495 return false;
496 }
497
498 if (boost::filesystem::exists(GetDataDir() / walletFile))
499 {
500 CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
501 if (r == CDBEnv::RECOVER_OK)
502 {
503 warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
504 " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
505 " your balance or transactions are incorrect you should"
506 " restore from a backup."), GetDataDir());
507 }
508 if (r == CDBEnv::RECOVER_FAIL)
509 errorString += _("wallet.dat corrupt, salvage failed");
510 }
511
512 return true;
513}
514
0f106047
JG
515template <class T>
516void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
731b89b8
GA
517{
518 // We want all the wallet transactions in range to have the same metadata as
519 // the oldest (smallest nOrderPos).
520 // So: find smallest nOrderPos:
521
522 int nMinOrderPos = std::numeric_limits<int>::max();
523 const CWalletTx* copyFrom = NULL;
0f106047 524 for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
731b89b8
GA
525 {
526 const uint256& hash = it->second;
527 int n = mapWallet[hash].nOrderPos;
528 if (n < nMinOrderPos)
529 {
530 nMinOrderPos = n;
531 copyFrom = &mapWallet[hash];
532 }
533 }
534 // Now copy data from copyFrom to rest:
0f106047 535 for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
731b89b8
GA
536 {
537 const uint256& hash = it->second;
538 CWalletTx* copyTo = &mapWallet[hash];
539 if (copyFrom == copyTo) continue;
540 copyTo->mapValue = copyFrom->mapValue;
c3a7307a
JG
541 // mapNoteData not copied on purpose
542 // (it is always set correctly for each CWalletTx)
731b89b8
GA
543 copyTo->vOrderForm = copyFrom->vOrderForm;
544 // fTimeReceivedIsTxTime not copied on purpose
545 // nTimeReceived not copied on purpose
546 copyTo->nTimeSmart = copyFrom->nTimeSmart;
547 copyTo->fFromMe = copyFrom->fFromMe;
548 copyTo->strFromAccount = copyFrom->strFromAccount;
731b89b8
GA
549 // nOrderPos not copied on purpose
550 // cached members not copied on purpose
551 }
552}
553
5b40d886
MF
554/**
555 * Outpoint is spent if any non-conflicted transaction
556 * spends it:
557 */
93a18a36 558bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
731b89b8 559{
93a18a36
GA
560 const COutPoint outpoint(hash, n);
561 pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
562 range = mapTxSpends.equal_range(outpoint);
731b89b8 563
93a18a36 564 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
731b89b8 565 {
93a18a36
GA
566 const uint256& wtxid = it->second;
567 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
568 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
569 return true; // Spent
731b89b8 570 }
93a18a36
GA
571 return false;
572}
573
0f106047
JG
574/**
575 * Note is spent if any non-conflicted transaction
576 * spends it:
577 */
578bool CWallet::IsSpent(const uint256& nullifier) const
579{
580 pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
581 range = mapTxNullifiers.equal_range(nullifier);
582
583 for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
584 const uint256& wtxid = it->second;
585 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
586 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
587 return true; // Spent
588 }
589 }
590 return false;
591}
592
93a18a36
GA
593void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
594{
595 mapTxSpends.insert(make_pair(outpoint, wtxid));
596
597 pair<TxSpends::iterator, TxSpends::iterator> range;
598 range = mapTxSpends.equal_range(outpoint);
0f106047 599 SyncMetaData<COutPoint>(range);
93a18a36
GA
600}
601
0f106047
JG
602void CWallet::AddToSpends(const uint256& nullifier, const uint256& wtxid)
603{
604 mapTxNullifiers.insert(make_pair(nullifier, wtxid));
605
606 pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
607 range = mapTxNullifiers.equal_range(nullifier);
608 SyncMetaData<uint256>(range);
609}
93a18a36
GA
610
611void CWallet::AddToSpends(const uint256& wtxid)
612{
613 assert(mapWallet.count(wtxid));
614 CWalletTx& thisTx = mapWallet[wtxid];
615 if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
616 return;
617
0f106047 618 for (const CTxIn& txin : thisTx.vin) {
93a18a36 619 AddToSpends(txin.prevout, wtxid);
0f106047
JG
620 }
621 for (const JSDescription& jsdesc : thisTx.vjoinsplit) {
622 for (const uint256& nullifier : jsdesc.nullifiers) {
623 AddToSpends(nullifier, wtxid);
624 }
625 }
731b89b8
GA
626}
627
76b22658
JG
628void CWallet::ClearNoteWitnessCache()
629{
630 LOCK(cs_wallet);
631 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
632 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
40600f50 633 item.second.witnesses.clear();
a4ef3aa9 634 item.second.witnessHeight = -1;
76b22658
JG
635 }
636 }
a4ef3aa9 637 nWitnessCacheSize = 0;
76b22658
JG
638}
639
be74c80d
JG
640void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
641 const CBlock* pblockIn,
b6961fc1 642 ZCIncrementalMerkleTree& tree)
be74c80d
JG
643{
644 {
645 LOCK(cs_wallet);
646 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
647 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
648 CNoteData* nd = &(item.second);
b6961fc1
JG
649 // Only increment witnesses that are behind the current height
650 if (nd->witnessHeight < pindex->nHeight) {
6f78f4f4
JG
651 // Check the validity of the cache
652 // The only time a note witnessed above the current height
653 // would be invalid here is during a reindex when blocks
654 // have been decremented, and we are incrementing the blocks
655 // immediately after.
656 assert(nWitnessCacheSize >= nd->witnesses.size());
b6961fc1 657 // Witnesses being incremented should always be either -1
40ef121e 658 // (never incremented or decremented) or one below pindex
b6961fc1
JG
659 assert((nd->witnessHeight == -1) ||
660 (nd->witnessHeight == pindex->nHeight - 1));
661 // Copy the witness for the previous block if we have one
662 if (nd->witnesses.size() > 0) {
663 nd->witnesses.push_front(nd->witnesses.front());
664 }
665 if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
666 nd->witnesses.pop_back();
667 }
be74c80d
JG
668 }
669 }
670 }
8a7d37be
DH
671 if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
672 nWitnessCacheSize += 1;
673 }
be74c80d
JG
674
675 const CBlock* pblock {pblockIn};
676 CBlock block;
677 if (!pblock) {
f2dd868d 678 ReadBlockFromDisk(block, pindex);
be74c80d
JG
679 pblock = &block;
680 }
681
be74c80d 682 for (const CTransaction& tx : pblock->vtx) {
fa511e10 683 auto hash = tx.GetHash();
be74c80d
JG
684 bool txIsOurs = mapWallet.count(hash);
685 for (size_t i = 0; i < tx.vjoinsplit.size(); i++) {
686 const JSDescription& jsdesc = tx.vjoinsplit[i];
687 for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) {
688 const uint256& note_commitment = jsdesc.commitments[j];
689 tree.append(note_commitment);
690
691 // Increment existing witnesses
692 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
693 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
694 CNoteData* nd = &(item.second);
b6961fc1
JG
695 if (nd->witnessHeight < pindex->nHeight &&
696 nd->witnesses.size() > 0) {
6f78f4f4
JG
697 // Check the validity of the cache
698 // See earlier comment about validity.
699 assert(nWitnessCacheSize >= nd->witnesses.size());
be74c80d
JG
700 nd->witnesses.front().append(note_commitment);
701 }
702 }
703 }
704
705 // If this is our note, witness it
706 if (txIsOurs) {
707 JSOutPoint jsoutpt {hash, i, j};
c0ec0e75
JG
708 if (mapWallet[hash].mapNoteData.count(jsoutpt) &&
709 mapWallet[hash].mapNoteData[jsoutpt].witnessHeight < pindex->nHeight) {
8e41408a 710 CNoteData* nd = &(mapWallet[hash].mapNoteData[jsoutpt]);
878c4b1b
JG
711 if (nd->witnesses.size() > 0) {
712 // We think this can happen because we write out the
713 // witness cache state after every block increment or
714 // decrement, but the block index itself is written in
715 // batches. So if the node crashes in between these two
716 // operations, it is possible for IncrementNoteWitnesses
717 // to be called again on previously-cached blocks. This
718 // doesn't affect existing cached notes because of the
719 // CNoteData::witnessHeight checks. See #1378 for details.
1b407cba 720 LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n",
878c4b1b 721 jsoutpt.ToString(), nd->witnesses.size(),
1b407cba 722 nd->witnessHeight,
878c4b1b 723 nd->witnesses.front().root().GetHex(),
1b407cba 724 pindex->nHeight,
878c4b1b
JG
725 tree.witness().root().GetHex());
726 nd->witnesses.clear();
727 }
8e41408a 728 nd->witnesses.push_front(tree.witness());
b6961fc1
JG
729 // Set height to one less than pindex so it gets incremented
730 nd->witnessHeight = pindex->nHeight - 1;
8e41408a
DH
731 // Check the validity of the cache
732 assert(nWitnessCacheSize >= nd->witnesses.size());
be74c80d
JG
733 }
734 }
735 }
736 }
737 }
b6961fc1
JG
738
739 // Update witness heights
83d7b5b6
JG
740 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
741 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
742 CNoteData* nd = &(item.second);
b6961fc1
JG
743 if (nd->witnessHeight < pindex->nHeight) {
744 nd->witnessHeight = pindex->nHeight;
6f78f4f4
JG
745 // Check the validity of the cache
746 // See earlier comment about validity.
747 assert(nWitnessCacheSize >= nd->witnesses.size());
b6961fc1 748 }
83d7b5b6
JG
749 }
750 }
b6961fc1 751
03f83b9b
JG
752 // For performance reasons, we write out the witness cache in
753 // CWallet::SetBestChain() (which also ensures that overall consistency
754 // of the wallet.dat is maintained).
be74c80d
JG
755 }
756}
757
40ef121e 758void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
be74c80d 759{
8432a64f 760 extern int32_t KOMODO_REWIND;
be74c80d
JG
761 {
762 LOCK(cs_wallet);
763 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
764 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
765 CNoteData* nd = &(item.second);
9d2cc3a7
JG
766 // Only increment witnesses that are not above the current height
767 if (nd->witnessHeight <= pindex->nHeight) {
6f78f4f4
JG
768 // Check the validity of the cache
769 // See comment below (this would be invalid if there was a
770 // prior decrement).
771 assert(nWitnessCacheSize >= nd->witnesses.size());
9d2cc3a7
JG
772 // Witnesses being decremented should always be either -1
773 // (never incremented or decremented) or equal to pindex
774 assert((nd->witnessHeight == -1) ||
775 (nd->witnessHeight == pindex->nHeight));
776 if (nd->witnesses.size() > 0) {
777 nd->witnesses.pop_front();
778 }
779 // pindex is the block being removed, so the new witness cache
780 // height is one below it.
781 nd->witnessHeight = pindex->nHeight - 1;
be74c80d
JG
782 }
783 }
784 }
4086e5ce 785 nWitnessCacheSize -= 1;
83d7b5b6
JG
786 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
787 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
788 CNoteData* nd = &(item.second);
789 // Check the validity of the cache
6f78f4f4
JG
790 // Technically if there are notes witnessed above the current
791 // height, their cache will now be invalid (relative to the new
792 // value of nWitnessCacheSize). However, this would only occur
793 // during a reindex, and by the time the reindex reaches the tip
794 // of the chain again, the existing witness caches will be valid
795 // again.
796 // We don't set nWitnessCacheSize to zero at the start of the
797 // reindex because the on-disk blocks had already resulted in a
798 // chain that didn't trigger the assertion below.
799 if (nd->witnessHeight < pindex->nHeight) {
800 assert(nWitnessCacheSize >= nd->witnesses.size());
801 }
83d7b5b6
JG
802 }
803 }
65195b3e 804 if ( nWitnessCacheSize <= 0 )
805 {
806 extern char ASSETCHAINS_SYMBOL[16];
807 fprintf(stderr,"%s nWitnessCacheSize.%d\n",ASSETCHAINS_SYMBOL,(int32_t)nWitnessCacheSize);
808 }
438eef93 809 if ( KOMODO_REWIND == 0 )
8432a64f 810 assert(nWitnessCacheSize > 0);
bc17ac49 811 //if (fFileBacked) {
812 // CWalletDB walletdb(strWalletFile);
813 // WriteWitnessCache(walletdb);
814 //}
03f83b9b
JG
815 // For performance reasons, we write out the witness cache in
816 // CWallet::SetBestChain() (which also ensures that overall consistency
817 // of the wallet.dat is maintained).
be74c80d
JG
818 }
819}
820
94f778bd 821bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
4e87d341 822{
6cc4a62c
GA
823 if (IsCrypted())
824 return false;
4e87d341 825
6cc4a62c
GA
826 CKeyingMaterial vMasterKey;
827 RandAddSeedPerfmon();
4e87d341 828
6cc4a62c 829 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
65e3a1e7 830 GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
4e87d341 831
6cc4a62c 832 CMasterKey kMasterKey;
6cc4a62c 833 RandAddSeedPerfmon();
001a53d7 834
6cc4a62c 835 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
65e3a1e7 836 GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
4e87d341 837
6cc4a62c 838 CCrypter crypter;
51ed9ec9 839 int64_t nStartTime = GetTimeMillis();
6cc4a62c
GA
840 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
841 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
ddebdd9a 842
6cc4a62c
GA
843 nStartTime = GetTimeMillis();
844 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
845 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
ddebdd9a 846
6cc4a62c
GA
847 if (kMasterKey.nDeriveIterations < 25000)
848 kMasterKey.nDeriveIterations = 25000;
ddebdd9a 849
881a85a2 850 LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
ddebdd9a 851
6cc4a62c
GA
852 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
853 return false;
854 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
855 return false;
4e87d341 856
6cc4a62c 857 {
f8dcd5ca 858 LOCK(cs_wallet);
4e87d341
MC
859 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
860 if (fFileBacked)
861 {
870da77d 862 assert(!pwalletdbEncryption);
96f34cd5 863 pwalletdbEncryption = new CWalletDB(strWalletFile);
870da77d
PK
864 if (!pwalletdbEncryption->TxnBegin()) {
865 delete pwalletdbEncryption;
866 pwalletdbEncryption = NULL;
0fb78eae 867 return false;
870da77d 868 }
96f34cd5 869 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
4e87d341
MC
870 }
871
872 if (!EncryptKeys(vMasterKey))
96f34cd5 873 {
870da77d 874 if (fFileBacked) {
96f34cd5 875 pwalletdbEncryption->TxnAbort();
870da77d
PK
876 delete pwalletdbEncryption;
877 }
878 // We now probably have half of our keys encrypted in memory, and half not...
7e6d23b1 879 // die and let the user reload the unencrypted wallet.
d0c4197e 880 assert(false);
96f34cd5
MC
881 }
882
0b807a41 883 // Encryption was introduced in version 0.4.0
439e1497 884 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
0b807a41 885
96f34cd5
MC
886 if (fFileBacked)
887 {
870da77d
PK
888 if (!pwalletdbEncryption->TxnCommit()) {
889 delete pwalletdbEncryption;
5b40d886 890 // We now have keys encrypted in memory, but not on disk...
7e6d23b1 891 // die to avoid confusion and let the user reload the unencrypted wallet.
d0c4197e 892 assert(false);
870da77d 893 }
96f34cd5 894
fcfd7ff8 895 delete pwalletdbEncryption;
96f34cd5
MC
896 pwalletdbEncryption = NULL;
897 }
4e87d341 898
37971fcc
GA
899 Lock();
900 Unlock(strWalletPassphrase);
901 NewKeyPool();
4e87d341 902 Lock();
6cc4a62c 903
d764d916
GA
904 // Need to completely rewrite the wallet file; if we don't, bdb might keep
905 // bits of the unencrypted private key in slack space in the database file.
b2d3b2d6 906 CDB::Rewrite(strWalletFile);
fe4a6550 907
d764d916 908 }
ab1b288f 909 NotifyStatusChanged(this);
9e9869d0 910
4e87d341 911 return true;
e8ef3da7
WL
912}
913
51ed9ec9 914int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
da7b8c12 915{
95691680 916 AssertLockHeld(cs_wallet); // nOrderPosNext
51ed9ec9 917 int64_t nRet = nOrderPosNext++;
4291e8fe
PW
918 if (pwalletdb) {
919 pwalletdb->WriteOrderPosNext(nOrderPosNext);
920 } else {
921 CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
922 }
da7b8c12
LD
923 return nRet;
924}
925
ddb709e9 926CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
c3f95ef1 927{
95691680 928 AssertLockHeld(cs_wallet); // mapWallet
c3f95ef1
LD
929 CWalletDB walletdb(strWalletFile);
930
931 // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
932 TxItems txOrdered;
933
934 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
935 // would make this much faster for applications that do this a lot.
936 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
937 {
938 CWalletTx* wtx = &((*it).second);
939 txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
940 }
ddb709e9 941 acentries.clear();
c3f95ef1
LD
942 walletdb.ListAccountCreditDebit(strAccount, acentries);
943 BOOST_FOREACH(CAccountingEntry& entry, acentries)
944 {
945 txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
946 }
947
948 return txOrdered;
949}
950
95d888a6
PW
951void CWallet::MarkDirty()
952{
95d888a6 953 {
f8dcd5ca 954 LOCK(cs_wallet);
95d888a6
PW
955 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
956 item.second.MarkDirty();
957 }
958}
959
1a62587e
JG
960/**
961 * Ensure that every note in the wallet has a cached nullifier.
962 */
963bool CWallet::UpdateNullifierNoteMap()
964{
965 {
966 LOCK(cs_wallet);
967
968 if (IsLocked())
969 return false;
970
971 ZCNoteDecryption dec;
972 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
973 for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
974 if (!item.second.nullifier) {
975 auto i = item.first.js;
976 GetNoteDecryptor(item.second.address, dec);
977 auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
978 *pzcashParams, wtxItem.second.joinSplitPubKey);
979 item.second.nullifier = GetNoteNullifier(
980 wtxItem.second.vjoinsplit[i],
981 item.second.address,
982 dec,
983 hSig,
984 item.first.n);
985 }
986 }
6e263a5f 987 UpdateNullifierNoteMapWithTx(wtxItem.second);
1a62587e
JG
988 }
989 }
990 return true;
991}
992
6e263a5f
JG
993/**
994 * Update mapNullifiersToNotes with the cached nullifiers in this tx.
995 */
996void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
8db7e25c
JG
997{
998 {
999 LOCK(cs_wallet);
1000 for (const mapNoteData_t::value_type& item : wtx.mapNoteData) {
1a62587e
JG
1001 if (item.second.nullifier) {
1002 mapNullifiersToNotes[*item.second.nullifier] = item.first;
1003 }
8db7e25c
JG
1004 }
1005 }
1006}
1007
44bc988e 1008bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
e8ef3da7 1009{
805344dc 1010 uint256 hash = wtxIn.GetHash();
731b89b8
GA
1011
1012 if (fFromLoadWallet)
1013 {
1014 mapWallet[hash] = wtxIn;
09ec3af1 1015 mapWallet[hash].BindWallet(this);
6e263a5f 1016 UpdateNullifierNoteMapWithTx(mapWallet[hash]);
93a18a36 1017 AddToSpends(hash);
731b89b8
GA
1018 }
1019 else
e8ef3da7 1020 {
f8dcd5ca 1021 LOCK(cs_wallet);
e8ef3da7
WL
1022 // Inserts only if not already there, returns tx inserted or tx found
1023 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
1024 CWalletTx& wtx = (*ret.first).second;
4c6e2295 1025 wtx.BindWallet(this);
6e263a5f 1026 UpdateNullifierNoteMapWithTx(wtx);
e8ef3da7
WL
1027 bool fInsertedNew = ret.second;
1028 if (fInsertedNew)
9c7722b7 1029 {
e8ef3da7 1030 wtx.nTimeReceived = GetAdjustedTime();
44bc988e 1031 wtx.nOrderPos = IncOrderPosNext(pwalletdb);
c3f95ef1
LD
1032
1033 wtx.nTimeSmart = wtx.nTimeReceived;
4f152496 1034 if (!wtxIn.hashBlock.IsNull())
c3f95ef1
LD
1035 {
1036 if (mapBlockIndex.count(wtxIn.hashBlock))
1037 {
209377a7 1038 int64_t latestNow = wtx.nTimeReceived;
1039 int64_t latestEntry = 0;
c3f95ef1
LD
1040 {
1041 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
51ed9ec9 1042 int64_t latestTolerated = latestNow + 300;
ddb709e9
LD
1043 std::list<CAccountingEntry> acentries;
1044 TxItems txOrdered = OrderedTxItems(acentries);
c3f95ef1
LD
1045 for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1046 {
1047 CWalletTx *const pwtx = (*it).second.first;
1048 if (pwtx == &wtx)
1049 continue;
1050 CAccountingEntry *const pacentry = (*it).second.second;
51ed9ec9 1051 int64_t nSmartTime;
c3f95ef1
LD
1052 if (pwtx)
1053 {
1054 nSmartTime = pwtx->nTimeSmart;
1055 if (!nSmartTime)
1056 nSmartTime = pwtx->nTimeReceived;
1057 }
1058 else
1059 nSmartTime = pacentry->nTime;
1060 if (nSmartTime <= latestTolerated)
1061 {
1062 latestEntry = nSmartTime;
1063 if (nSmartTime > latestNow)
1064 latestNow = nSmartTime;
1065 break;
1066 }
1067 }
1068 }
1069
209377a7 1070 int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
c3f95ef1
LD
1071 wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
1072 }
1073 else
5262fde0 1074 LogPrintf("AddToWallet(): found %s in block %s not in index\n",
805344dc 1075 wtxIn.GetHash().ToString(),
7d9d134b 1076 wtxIn.hashBlock.ToString());
c3f95ef1 1077 }
93a18a36 1078 AddToSpends(hash);
9c7722b7 1079 }
e8ef3da7
WL
1080
1081 bool fUpdated = false;
1082 if (!fInsertedNew)
1083 {
1084 // Merge
4f152496 1085 if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
e8ef3da7
WL
1086 {
1087 wtx.hashBlock = wtxIn.hashBlock;
1088 fUpdated = true;
1089 }
1090 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
1091 {
1092 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
1093 wtx.nIndex = wtxIn.nIndex;
1094 fUpdated = true;
1095 }
ac1c9435 1096 if (UpdatedNoteData(wtxIn, wtx)) {
c3a7307a
JG
1097 fUpdated = true;
1098 }
e8ef3da7
WL
1099 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
1100 {
1101 wtx.fFromMe = wtxIn.fFromMe;
1102 fUpdated = true;
1103 }
e8ef3da7
WL
1104 }
1105
1106 //// debug print
805344dc 1107 LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
e8ef3da7
WL
1108
1109 // Write to disk
1110 if (fInsertedNew || fUpdated)
44bc988e 1111 if (!wtx.WriteToDisk(pwalletdb))
e8ef3da7 1112 return false;
ee4b170c 1113
93a18a36
GA
1114 // Break debit/credit balance caches:
1115 wtx.MarkDirty();
e8ef3da7 1116
fe4a6550
WL
1117 // Notify UI of new or updated transaction
1118 NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
cae686d3 1119
1120 // notify an external script when a wallet transaction comes in or is updated
1121 std::string strCmd = GetArg("-walletnotify", "");
1122
1123 if ( !strCmd.empty())
1124 {
805344dc 1125 boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
cae686d3 1126 boost::thread t(runCommand, strCmd); // thread runs free
1127 }
1128
fe4a6550 1129 }
e8ef3da7
WL
1130 return true;
1131}
1132
ac1c9435
JG
1133bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
1134{
1135 if (wtxIn.mapNoteData.empty() || wtxIn.mapNoteData == wtx.mapNoteData) {
1136 return false;
1137 }
1138 auto tmp = wtxIn.mapNoteData;
1139 // Ensure we keep any cached witnesses we may already have
1140 for (const std::pair<JSOutPoint, CNoteData> nd : wtx.mapNoteData) {
1141 if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
1142 tmp.at(nd.first).witnesses.assign(
1143 nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
1144 }
4a6a4847 1145 tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
ac1c9435
JG
1146 }
1147 // Now copy over the updated note data
1148 wtx.mapNoteData = tmp;
1149 return true;
1150}
1151
5b40d886
MF
1152/**
1153 * Add a transaction to the wallet, or update it.
1154 * pblock is optional, but should be provided if the transaction is known to be in a block.
1155 * If fUpdate is true, existing transactions will be updated.
1156 */
d38da59b 1157bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
e8ef3da7 1158{
e8ef3da7 1159 {
53d56881 1160 AssertLockHeld(cs_wallet);
805344dc 1161 bool fExisted = mapWallet.count(tx.GetHash()) != 0;
6cc4a62c 1162 if (fExisted && !fUpdate) return false;
c3a7307a
JG
1163 auto noteData = FindMyNotes(tx);
1164 if (fExisted || IsMine(tx) || IsFromMe(tx) || noteData.size() > 0)
6cc4a62c
GA
1165 {
1166 CWalletTx wtx(this,tx);
44bc988e 1167
be74c80d 1168 if (noteData.size() > 0) {
c3a7307a 1169 wtx.SetNoteData(noteData);
be74c80d 1170 }
c3a7307a 1171
6cc4a62c
GA
1172 // Get merkle branch if transaction was found in a block
1173 if (pblock)
4b0deb3b 1174 wtx.SetMerkleBranch(*pblock);
44bc988e
CL
1175
1176 // Do not flush the wallet here for performance reasons
1177 // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
1178 CWalletDB walletdb(strWalletFile, "r+", false);
1179
1180 return AddToWallet(wtx, false, &walletdb);
6cc4a62c 1181 }
e8ef3da7 1182 }
e8ef3da7
WL
1183 return false;
1184}
1185
d38da59b 1186void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
93a18a36 1187{
55a1db4f 1188 LOCK2(cs_main, cs_wallet);
d38da59b 1189 if (!AddToWalletIfInvolvingMe(tx, pblock, true))
93a18a36
GA
1190 return; // Not one of ours
1191
ac1c9435
JG
1192 MarkAffectedTransactionsDirty(tx);
1193}
1194
1195void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx)
1196{
93a18a36
GA
1197 // If a transaction changes 'conflicted' state, that changes the balance
1198 // available of the outputs it spends. So force those to be
1199 // recomputed, also:
1200 BOOST_FOREACH(const CTxIn& txin, tx.vin)
1201 {
1202 if (mapWallet.count(txin.prevout.hash))
1203 mapWallet[txin.prevout.hash].MarkDirty();
1204 }
8db7e25c
JG
1205 for (const JSDescription& jsdesc : tx.vjoinsplit) {
1206 for (const uint256& nullifier : jsdesc.nullifiers) {
ad20f214
JG
1207 if (mapNullifiersToNotes.count(nullifier) &&
1208 mapWallet.count(mapNullifiersToNotes[nullifier].hash)) {
1209 mapWallet[mapNullifiersToNotes[nullifier].hash].MarkDirty();
8db7e25c
JG
1210 }
1211 }
1212 }
00588c3f
PW
1213}
1214
1215void CWallet::EraseFromWallet(const uint256 &hash)
e8ef3da7
WL
1216{
1217 if (!fFileBacked)
00588c3f 1218 return;
e8ef3da7 1219 {
f8dcd5ca 1220 LOCK(cs_wallet);
e8ef3da7
WL
1221 if (mapWallet.erase(hash))
1222 CWalletDB(strWalletFile).EraseTx(hash);
1223 }
00588c3f 1224 return;
e8ef3da7
WL
1225}
1226
1227
1a62587e
JG
1228/**
1229 * Returns a nullifier if the SpendingKey is available
1230 * Throws std::runtime_error if the decryptor doesn't match this note
1231 */
1232boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
1233 const libzcash::PaymentAddress& address,
1234 const ZCNoteDecryption& dec,
1235 const uint256& hSig,
1236 uint8_t n) const
1237{
1238 boost::optional<uint256> ret;
1239 auto note_pt = libzcash::NotePlaintext::decrypt(
1240 dec,
1241 jsdesc.ciphertexts[n],
1242 jsdesc.ephemeralKey,
1243 hSig,
1244 (unsigned char) n);
1245 auto note = note_pt.note(address);
1246 // SpendingKeys are only available if the wallet is unlocked
1247 libzcash::SpendingKey key;
1248 if (GetSpendingKey(address, key)) {
1249 ret = note.nullifier(key);
1250 }
1251 return ret;
1252}
1253
e492d986
JG
1254/**
1255 * Finds all output notes in the given transaction that have been sent to
1256 * PaymentAddresses in this wallet.
1257 *
1258 * It should never be necessary to call this method with a CWalletTx, because
1259 * the result of FindMyNotes (for the addresses available at the time) will
1260 * already have been cached in CWalletTx.mapNoteData.
1261 */
02e67455
JG
1262mapNoteData_t CWallet::FindMyNotes(const CTransaction& tx) const
1263{
3fac1020 1264 LOCK(cs_SpendingKeyStore);
fa511e10 1265 uint256 hash = tx.GetHash();
02e67455
JG
1266
1267 mapNoteData_t noteData;
02e67455
JG
1268 for (size_t i = 0; i < tx.vjoinsplit.size(); i++) {
1269 auto hSig = tx.vjoinsplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey);
1270 for (uint8_t j = 0; j < tx.vjoinsplit[i].ciphertexts.size(); j++) {
3fac1020 1271 for (const NoteDecryptorMap::value_type& item : mapNoteDecryptors) {
02e67455 1272 try {
02e67455 1273 auto address = item.first;
02e67455 1274 JSOutPoint jsoutpt {hash, i, j};
1a62587e
JG
1275 auto nullifier = GetNoteNullifier(
1276 tx.vjoinsplit[i],
1277 address,
1278 item.second,
1279 hSig, j);
1280 if (nullifier) {
1281 CNoteData nd {address, *nullifier};
1282 noteData.insert(std::make_pair(jsoutpt, nd));
1283 } else {
1284 CNoteData nd {address};
1285 noteData.insert(std::make_pair(jsoutpt, nd));
1286 }
02e67455 1287 break;
a581fe2a
JG
1288 } catch (const std::runtime_error &err) {
1289 if (memcmp("Could not decrypt message", err.what(), 25) != 0) {
1290 // Unexpected failure
1291 LogPrintf("FindMyNotes(): Unexpected runtime error while testing decrypt:\n");
1292 LogPrintf("%s\n", err.what());
1293 } // else
1a62587e 1294 // Couldn't decrypt with this decryptor
32a103aa
JG
1295 } catch (const std::exception &exc) {
1296 // Unexpected failure
1297 LogPrintf("FindMyNotes(): Unexpected error while testing decrypt:\n");
1298 LogPrintf("%s\n", exc.what());
02e67455
JG
1299 }
1300 }
1301 }
1302 }
1303 return noteData;
1304}
1305
1551db87
JG
1306bool CWallet::IsFromMe(const uint256& nullifier) const
1307{
1308 {
1309 LOCK(cs_wallet);
1310 if (mapNullifiersToNotes.count(nullifier) &&
1311 mapWallet.count(mapNullifiersToNotes.at(nullifier).hash)) {
1312 return true;
1313 }
1314 }
1315 return false;
1316}
1317
be74c80d
JG
1318void CWallet::GetNoteWitnesses(std::vector<JSOutPoint> notes,
1319 std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
1320 uint256 &final_anchor)
1321{
1322 {
1323 LOCK(cs_wallet);
1324 witnesses.resize(notes.size());
4086e5ce 1325 boost::optional<uint256> rt;
be74c80d
JG
1326 int i = 0;
1327 for (JSOutPoint note : notes) {
1328 if (mapWallet.count(note.hash) &&
1329 mapWallet[note.hash].mapNoteData.count(note) &&
1330 mapWallet[note.hash].mapNoteData[note].witnesses.size() > 0) {
1331 witnesses[i] = mapWallet[note.hash].mapNoteData[note].witnesses.front();
4086e5ce
JG
1332 if (!rt) {
1333 rt = witnesses[i]->root();
1334 } else {
1335 assert(*rt == witnesses[i]->root());
1336 }
be74c80d
JG
1337 }
1338 i++;
1339 }
4086e5ce
JG
1340 // All returned witnesses have the same anchor
1341 if (rt) {
1342 final_anchor = *rt;
be74c80d
JG
1343 }
1344 }
1345}
1346
c8988460 1347isminetype CWallet::IsMine(const CTxIn &txin) const
e8ef3da7 1348{
e8ef3da7 1349 {
f8dcd5ca 1350 LOCK(cs_wallet);
e8ef3da7
WL
1351 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1352 if (mi != mapWallet.end())
1353 {
1354 const CWalletTx& prev = (*mi).second;
1355 if (txin.prevout.n < prev.vout.size())
c8988460 1356 return IsMine(prev.vout[txin.prevout.n]);
e8ef3da7
WL
1357 }
1358 }
a3e192a3 1359 return ISMINE_NO;
e8ef3da7
WL
1360}
1361
a372168e 1362CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
e8ef3da7 1363{
e8ef3da7 1364 {
f8dcd5ca 1365 LOCK(cs_wallet);
e8ef3da7
WL
1366 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
1367 if (mi != mapWallet.end())
1368 {
1369 const CWalletTx& prev = (*mi).second;
1370 if (txin.prevout.n < prev.vout.size())
d4640d7d 1371 if (IsMine(prev.vout[txin.prevout.n]) & filter)
47658758 1372 return prev.vout[txin.prevout.n].nValue; // komodo_interest?
e8ef3da7
WL
1373 }
1374 }
1375 return 0;
1376}
1377
eca0b1ea
JT
1378isminetype CWallet::IsMine(const CTxOut& txout) const
1379{
1380 return ::IsMine(*this, txout.scriptPubKey);
1381}
1382
1383CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
1384{
1385 if (!MoneyRange(txout.nValue))
1386 throw std::runtime_error("CWallet::GetCredit(): value out of range");
1387 return ((IsMine(txout) & filter) ? txout.nValue : 0);
1388}
1389
e679ec96
GA
1390bool CWallet::IsChange(const CTxOut& txout) const
1391{
2a45a494 1392 // TODO: fix handling of 'change' outputs. The assumption is that any
d5087d1b 1393 // payment to a script that is ours, but is not in the address book
2a45a494
GA
1394 // is change. That assumption is likely to break when we implement multisignature
1395 // wallets that return change back into a multi-signature-protected address;
1396 // a better way of identifying which outputs are 'the send' and which are
1397 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
1398 // which output, if any, was change).
d5087d1b 1399 if (::IsMine(*this, txout.scriptPubKey))
f8dcd5ca 1400 {
d5087d1b
PW
1401 CTxDestination address;
1402 if (!ExtractDestination(txout.scriptPubKey, address))
1403 return true;
1404
f8dcd5ca
PW
1405 LOCK(cs_wallet);
1406 if (!mapAddressBook.count(address))
1407 return true;
1408 }
e679ec96
GA
1409 return false;
1410}
1411
eca0b1ea
JT
1412CAmount CWallet::GetChange(const CTxOut& txout) const
1413{
1414 if (!MoneyRange(txout.nValue))
1415 throw std::runtime_error("CWallet::GetChange(): value out of range");
1416 return (IsChange(txout) ? txout.nValue : 0);
1417}
1418
1419bool CWallet::IsMine(const CTransaction& tx) const
1420{
1421 BOOST_FOREACH(const CTxOut& txout, tx.vout)
1422 if (IsMine(txout))
1423 return true;
1424 return false;
1425}
1426
1427bool CWallet::IsFromMe(const CTransaction& tx) const
1428{
1551db87
JG
1429 if (GetDebit(tx, ISMINE_ALL) > 0) {
1430 return true;
1431 }
1432 for (const JSDescription& jsdesc : tx.vjoinsplit) {
1433 for (const uint256& nullifier : jsdesc.nullifiers) {
1434 if (IsFromMe(nullifier)) {
1435 return true;
1436 }
1437 }
1438 }
1439 return false;
eca0b1ea
JT
1440}
1441
1442CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
1443{
1444 CAmount nDebit = 0;
1445 BOOST_FOREACH(const CTxIn& txin, tx.vin)
1446 {
1447 nDebit += GetDebit(txin, filter);
1448 if (!MoneyRange(nDebit))
1449 throw std::runtime_error("CWallet::GetDebit(): value out of range");
1450 }
1451 return nDebit;
1452}
1453
1454CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const
1455{
1456 CAmount nCredit = 0;
1457 BOOST_FOREACH(const CTxOut& txout, tx.vout)
1458 {
1459 nCredit += GetCredit(txout, filter);
1460 if (!MoneyRange(nCredit))
1461 throw std::runtime_error("CWallet::GetCredit(): value out of range");
1462 }
1463 return nCredit;
1464}
1465
1466CAmount CWallet::GetChange(const CTransaction& tx) const
1467{
1468 CAmount nChange = 0;
1469 BOOST_FOREACH(const CTxOut& txout, tx.vout)
1470 {
1471 nChange += GetChange(txout);
1472 if (!MoneyRange(nChange))
1473 throw std::runtime_error("CWallet::GetChange(): value out of range");
1474 }
1475 return nChange;
1476}
1477
c3a7307a
JG
1478void CWalletTx::SetNoteData(mapNoteData_t &noteData)
1479{
1480 mapNoteData.clear();
1481 for (const std::pair<JSOutPoint, CNoteData> nd : noteData) {
1482 if (nd.first.js < vjoinsplit.size() &&
1483 nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) {
1484 // Store the address and nullifier for the Note
1485 mapNoteData[nd.first] = nd.second;
1486 } else {
1487 // If FindMyNotes() was used to obtain noteData,
1488 // this should never happen
32a103aa 1489 throw std::logic_error("CWalletTx::SetNoteData(): Invalid note");
c3a7307a
JG
1490 }
1491 }
1492}
1493
51ed9ec9 1494int64_t CWalletTx::GetTxTime() const
e8ef3da7 1495{
51ed9ec9 1496 int64_t n = nTimeSmart;
c3f95ef1 1497 return n ? n : nTimeReceived;
e8ef3da7
WL
1498}
1499
1500int CWalletTx::GetRequestCount() const
1501{
1502 // Returns -1 if it wasn't being tracked
1503 int nRequests = -1;
e8ef3da7 1504 {
f8dcd5ca 1505 LOCK(pwallet->cs_wallet);
e8ef3da7
WL
1506 if (IsCoinBase())
1507 {
1508 // Generated block
4f152496 1509 if (!hashBlock.IsNull())
e8ef3da7
WL
1510 {
1511 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
1512 if (mi != pwallet->mapRequestCount.end())
1513 nRequests = (*mi).second;
1514 }
1515 }
1516 else
1517 {
1518 // Did anyone request this transaction?
805344dc 1519 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
e8ef3da7
WL
1520 if (mi != pwallet->mapRequestCount.end())
1521 {
1522 nRequests = (*mi).second;
1523
1524 // How about the block it's in?
4f152496 1525 if (nRequests == 0 && !hashBlock.IsNull())
e8ef3da7
WL
1526 {
1527 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
1528 if (mi != pwallet->mapRequestCount.end())
1529 nRequests = (*mi).second;
1530 else
1531 nRequests = 1; // If it's in someone else's block it must have got out
1532 }
1533 }
1534 }
1535 }
1536 return nRequests;
1537}
1538
86cf60b5 1539// GetAmounts will determine the transparent debits and credits for a given wallet tx.
1b4568cb 1540void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
a372168e 1541 list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
e8ef3da7 1542{
e07c8e91 1543 nFee = 0;
e8ef3da7
WL
1544 listReceived.clear();
1545 listSent.clear();
1546 strSentAccount = strFromAccount;
1547
86cf60b5 1548 // Is this tx sent/signed by me?
a372168e 1549 CAmount nDebit = GetDebit(filter);
86cf60b5
S
1550 bool isFromMyTaddr = nDebit > 0; // debit>0 means we signed/sent this transaction
1551
1552 // Does this tx spend my notes?
1553 bool isFromMyZaddr = false;
1554 for (const JSDescription& js : vjoinsplit) {
1555 for (const uint256& nullifier : js.nullifiers) {
1556 if (pwallet->IsFromMe(nullifier)) {
1557 isFromMyZaddr = true;
1558 break;
1559 }
1560 }
1561 if (isFromMyZaddr) {
1562 break;
1563 }
1564 }
1565
1566 // Compute fee if we sent this transaction.
1567 if (isFromMyTaddr) {
1568 CAmount nValueOut = GetValueOut(); // transparent outputs plus all vpub_old
1569 CAmount nValueIn = 0;
1570 for (const JSDescription & js : vjoinsplit) {
1571 nValueIn += js.vpub_new;
1572 }
1573 nFee = nDebit - nValueOut + nValueIn;
1574 }
1575
1576 // Create output entry for vpub_old/new, if we sent utxos from this transaction
1577 if (isFromMyTaddr) {
1578 CAmount myVpubOld = 0;
1579 CAmount myVpubNew = 0;
1580 for (const JSDescription& js : vjoinsplit) {
1581 bool fMyJSDesc = false;
1582
1583 // Check input side
1584 for (const uint256& nullifier : js.nullifiers) {
1585 if (pwallet->IsFromMe(nullifier)) {
1586 fMyJSDesc = true;
1587 break;
1588 }
1589 }
1590
1591 // Check output side
1592 if (!fMyJSDesc) {
1593 for (const std::pair<JSOutPoint, CNoteData> nd : this->mapNoteData) {
1594 if (nd.first.js < vjoinsplit.size() && nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) {
1595 fMyJSDesc = true;
1596 break;
1597 }
1598 }
1599 }
1600
1601 if (fMyJSDesc) {
1602 myVpubOld += js.vpub_old;
1603 myVpubNew += js.vpub_new;
1604 }
1605
1606 if (!MoneyRange(js.vpub_old) || !MoneyRange(js.vpub_new) || !MoneyRange(myVpubOld) || !MoneyRange(myVpubNew)) {
1607 throw std::runtime_error("CWalletTx::GetAmounts: value out of range");
1608 }
1609 }
1610
1611 // Create an output for the value taken from or added to the transparent value pool by JoinSplits
1612 if (myVpubOld > myVpubNew) {
1613 COutputEntry output = {CNoDestination(), myVpubOld - myVpubNew, (int)vout.size()};
1614 listSent.push_back(output);
1615 } else if (myVpubNew > myVpubOld) {
1616 COutputEntry output = {CNoDestination(), myVpubNew - myVpubOld, (int)vout.size()};
1617 listReceived.push_back(output);
1618 }
e8ef3da7
WL
1619 }
1620
e679ec96 1621 // Sent/received.
5bb76550 1622 for (unsigned int i = 0; i < vout.size(); ++i)
e8ef3da7 1623 {
1b4568cb 1624 const CTxOut& txout = vout[i];
a5c6c5d6 1625 isminetype fIsMine = pwallet->IsMine(txout);
96ed6821
LD
1626 // Only need to handle txouts if AT LEAST one of these is true:
1627 // 1) they debit from us (sent)
1628 // 2) the output is to us (received)
1629 if (nDebit > 0)
1630 {
1631 // Don't report 'change' txouts
1632 if (pwallet->IsChange(txout))
1633 continue;
96ed6821 1634 }
a5c6c5d6 1635 else if (!(fIsMine & filter))
96ed6821
LD
1636 continue;
1637
1638 // In either case, we need to get the destination address
10254401 1639 CTxDestination address;
10254401 1640 if (!ExtractDestination(txout.scriptPubKey, address))
e8ef3da7 1641 {
7d306d64 1642 //LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",this->GetHash().ToString()); complains on the opreturns
96ed6821 1643 address = CNoDestination();
e8ef3da7
WL
1644 }
1645
5bb76550 1646 COutputEntry output = {address, txout.nValue, (int)i};
1b4568cb 1647
96ed6821 1648 // If we are debited by the transaction, add the output as a "sent" entry
e8ef3da7 1649 if (nDebit > 0)
1b4568cb 1650 listSent.push_back(output);
e8ef3da7 1651
96ed6821 1652 // If we are receiving the output, add it as a "received" entry
d512534c 1653 if (fIsMine & filter)
1b4568cb 1654 listReceived.push_back(output);
e8ef3da7
WL
1655 }
1656
1657}
1658
a372168e
MF
1659void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
1660 CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
e8ef3da7 1661{
e07c8e91 1662 nReceived = nSent = nFee = 0;
e8ef3da7 1663
a372168e 1664 CAmount allFee;
e8ef3da7 1665 string strSentAccount;
1b4568cb
CL
1666 list<COutputEntry> listReceived;
1667 list<COutputEntry> listSent;
d4640d7d 1668 GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
e8ef3da7 1669
e8ef3da7
WL
1670 if (strAccount == strSentAccount)
1671 {
1b4568cb
CL
1672 BOOST_FOREACH(const COutputEntry& s, listSent)
1673 nSent += s.amount;
e8ef3da7
WL
1674 nFee = allFee;
1675 }
e8ef3da7 1676 {
f8dcd5ca 1677 LOCK(pwallet->cs_wallet);
1b4568cb 1678 BOOST_FOREACH(const COutputEntry& r, listReceived)
e8ef3da7 1679 {
1b4568cb 1680 if (pwallet->mapAddressBook.count(r.destination))
e8ef3da7 1681 {
1b4568cb 1682 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
61885513 1683 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
1b4568cb 1684 nReceived += r.amount;
e8ef3da7
WL
1685 }
1686 else if (strAccount.empty())
1687 {
1b4568cb 1688 nReceived += r.amount;
e8ef3da7
WL
1689 }
1690 }
1691 }
1692}
1693
722fa283 1694
44bc988e 1695bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
e8ef3da7 1696{
805344dc 1697 return pwalletdb->WriteTx(GetHash(), *this);
e8ef3da7
WL
1698}
1699
4bc00dc1
DH
1700void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
1701 std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
1702 uint256 &final_anchor)
a8ac403d 1703{
2dc35992 1704 witnesses.resize(commitments.size());
a8ac403d 1705 CBlockIndex* pindex = chainActive.Genesis();
1760b3cd 1706 ZCIncrementalMerkleTree tree;
a8ac403d
SB
1707
1708 while (pindex) {
1709 CBlock block;
f2dd868d 1710 ReadBlockFromDisk(block, pindex);
a8ac403d
SB
1711
1712 BOOST_FOREACH(const CTransaction& tx, block.vtx)
1713 {
22de1602 1714 BOOST_FOREACH(const JSDescription& jsdesc, tx.vjoinsplit)
a8ac403d 1715 {
22de1602 1716 BOOST_FOREACH(const uint256 &note_commitment, jsdesc.commitments)
a8ac403d 1717 {
4bc00dc1 1718 tree.append(note_commitment);
1760b3cd 1719
2dc35992
SB
1720 BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) {
1721 if (wit) {
4bc00dc1 1722 wit->append(note_commitment);
2dc35992
SB
1723 }
1724 }
1725
1726 size_t i = 0;
1727 BOOST_FOREACH(uint256& commitment, commitments) {
4bc00dc1 1728 if (note_commitment == commitment) {
2dc35992 1729 witnesses.at(i) = tree.witness();
1760b3cd 1730 }
2dc35992 1731 i++;
a8ac403d
SB
1732 }
1733 }
1734 }
1735 }
1736
ccb439c5 1737 uint256 current_anchor = tree.root();
a8ac403d
SB
1738
1739 // Consistency check: we should be able to find the current tree
1740 // in our CCoins view.
434f3284 1741 ZCIncrementalMerkleTree dummy_tree;
a8ac403d
SB
1742 assert(pcoinsTip->GetAnchorAt(current_anchor, dummy_tree));
1743
1744 pindex = chainActive.Next(pindex);
1745 }
1746
ccb439c5
SB
1747 // TODO: #93; Select a root via some heuristic.
1748 final_anchor = tree.root();
a8ac403d 1749
2dc35992
SB
1750 BOOST_FOREACH(boost::optional<ZCIncrementalWitness>& wit, witnesses) {
1751 if (wit) {
1752 assert(final_anchor == wit->root());
1753 }
1760b3cd 1754 }
a8ac403d
SB
1755}
1756
5b40d886
MF
1757/**
1758 * Scan the block chain (starting in pindexStart) for transactions
1759 * from or to us. If fUpdate is true, found transactions that already
1760 * exist in the wallet will be updated.
1761 */
e8ef3da7
WL
1762int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
1763{
1764 int ret = 0;
75b8953a 1765 int64_t nNow = GetTime();
11982d36 1766 const CChainParams& chainParams = Params();
e8ef3da7
WL
1767
1768 CBlockIndex* pindex = pindexStart;
e8ef3da7 1769 {
55a1db4f 1770 LOCK2(cs_main, cs_wallet);
39278369
CL
1771
1772 // no need to read and scan block, if block was created before
1773 // our wallet birthday (as adjusted for block time variability)
209377a7 1774 while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200)))
39278369
CL
1775 pindex = chainActive.Next(pindex);
1776
1777 ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
11982d36
CF
1778 double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false);
1779 double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false);
e8ef3da7
WL
1780 while (pindex)
1781 {
39278369 1782 if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
11982d36 1783 ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
8da9dd07 1784
e8ef3da7 1785 CBlock block;
f2dd868d 1786 ReadBlockFromDisk(block, pindex);
e8ef3da7
WL
1787 BOOST_FOREACH(CTransaction& tx, block.vtx)
1788 {
d38da59b 1789 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
e8ef3da7
WL
1790 ret++;
1791 }
b6961fc1
JG
1792
1793 ZCIncrementalMerkleTree tree;
1794 // This should never fail: we should always be able to get the tree
1795 // state on the path to the tip of our chain
1796 assert(pcoinsTip->GetAnchorAt(pindex->hashAnchor, tree));
1797 // Increment note witness caches
1798 IncrementNoteWitnesses(pindex, &block, tree);
1799
4c6d41b8 1800 pindex = chainActive.Next(pindex);
75b8953a
B
1801 if (GetTime() >= nNow + 60) {
1802 nNow = GetTime();
11982d36 1803 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
75b8953a 1804 }
e8ef3da7 1805 }
39278369 1806 ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
e8ef3da7
WL
1807 }
1808 return ret;
1809}
1810
1811void CWallet::ReacceptWalletTransactions()
1812{
7e6d23b1 1813 // If transactions aren't being broadcasted, don't let them into local mempool either
6f252627
WL
1814 if (!fBroadcastTransactions)
1815 return;
55a1db4f 1816 LOCK2(cs_main, cs_wallet);
e9c3215b 1817 std::map<int64_t, CWalletTx*> mapSorted;
1818
1819 // Sort pending wallet transactions based on their initial wallet insertion order
93a18a36 1820 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
e8ef3da7 1821 {
93a18a36
GA
1822 const uint256& wtxid = item.first;
1823 CWalletTx& wtx = item.second;
805344dc 1824 assert(wtx.GetHash() == wtxid);
e8ef3da7 1825
93a18a36
GA
1826 int nDepth = wtx.GetDepthInMainChain();
1827
e9c3215b 1828 if (!wtx.IsCoinBase() && nDepth < 0) {
1829 mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
e8ef3da7
WL
1830 }
1831 }
e9c3215b 1832
1833 // Try to add wallet transactions to memory pool
1834 BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted)
1835 {
1836 CWalletTx& wtx = *(item.second);
1837
1838 LOCK(mempool.cs);
1839 wtx.AcceptToMemoryPool(false);
1840 }
e8ef3da7
WL
1841}
1842
0f5954c4 1843bool CWalletTx::RelayWalletTransaction()
e8ef3da7 1844{
6f252627 1845 assert(pwallet->GetBroadcastTransactions());
e8ef3da7
WL
1846 if (!IsCoinBase())
1847 {
5eaf91a4 1848 if (GetDepthInMainChain() == 0) {
805344dc 1849 LogPrintf("Relaying wtx %s\n", GetHash().ToString());
d38da59b 1850 RelayTransaction((CTransaction)*this);
0f5954c4 1851 return true;
e8ef3da7
WL
1852 }
1853 }
0f5954c4 1854 return false;
e8ef3da7
WL
1855}
1856
3015e0bc 1857set<uint256> CWalletTx::GetConflicts() const
731b89b8
GA
1858{
1859 set<uint256> result;
1860 if (pwallet != NULL)
1861 {
805344dc 1862 uint256 myHash = GetHash();
3015e0bc 1863 result = pwallet->GetConflicts(myHash);
731b89b8
GA
1864 result.erase(myHash);
1865 }
1866 return result;
1867}
1868
bbacd882
CF
1869CAmount CWalletTx::GetDebit(const isminefilter& filter) const
1870{
1871 if (vin.empty())
1872 return 0;
1873
1874 CAmount debit = 0;
1875 if(filter & ISMINE_SPENDABLE)
1876 {
1877 if (fDebitCached)
1878 debit += nDebitCached;
1879 else
1880 {
1881 nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
1882 fDebitCached = true;
1883 debit += nDebitCached;
1884 }
1885 }
1886 if(filter & ISMINE_WATCH_ONLY)
1887 {
1888 if(fWatchDebitCached)
1889 debit += nWatchDebitCached;
1890 else
1891 {
1892 nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
1893 fWatchDebitCached = true;
1894 debit += nWatchDebitCached;
1895 }
1896 }
1897 return debit;
1898}
1899
1900CAmount CWalletTx::GetCredit(const isminefilter& filter) const
1901{
1902 // Must wait until coinbase is safely deep enough in the chain before valuing it
1903 if (IsCoinBase() && GetBlocksToMaturity() > 0)
1904 return 0;
1905
1906 int64_t credit = 0;
1907 if (filter & ISMINE_SPENDABLE)
1908 {
1909 // GetBalance can assume transactions in mapWallet won't change
1910 if (fCreditCached)
1911 credit += nCreditCached;
1912 else
1913 {
1914 nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
1915 fCreditCached = true;
1916 credit += nCreditCached;
1917 }
1918 }
1919 if (filter & ISMINE_WATCH_ONLY)
1920 {
1921 if (fWatchCreditCached)
1922 credit += nWatchCreditCached;
1923 else
1924 {
1925 nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
1926 fWatchCreditCached = true;
1927 credit += nWatchCreditCached;
1928 }
1929 }
1930 return credit;
1931}
1932
1933CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
1934{
1935 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
1936 {
1937 if (fUseCache && fImmatureCreditCached)
1938 return nImmatureCreditCached;
1939 nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
1940 fImmatureCreditCached = true;
1941 return nImmatureCreditCached;
1942 }
1943
1944 return 0;
1945}
1946
1947CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
1948{
1949 if (pwallet == 0)
1950 return 0;
1951
1952 // Must wait until coinbase is safely deep enough in the chain before valuing it
1953 if (IsCoinBase() && GetBlocksToMaturity() > 0)
1954 return 0;
1955
1956 if (fUseCache && fAvailableCreditCached)
1957 return nAvailableCreditCached;
1958
1959 CAmount nCredit = 0;
805344dc 1960 uint256 hashTx = GetHash();
bbacd882
CF
1961 for (unsigned int i = 0; i < vout.size(); i++)
1962 {
1963 if (!pwallet->IsSpent(hashTx, i))
1964 {
1965 const CTxOut &txout = vout[i];
1966 nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
1967 if (!MoneyRange(nCredit))
1968 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
1969 }
1970 }
1971
1972 nAvailableCreditCached = nCredit;
1973 fAvailableCreditCached = true;
1974 return nCredit;
1975}
1976
1977CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
1978{
1979 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
1980 {
1981 if (fUseCache && fImmatureWatchCreditCached)
1982 return nImmatureWatchCreditCached;
1983 nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
1984 fImmatureWatchCreditCached = true;
1985 return nImmatureWatchCreditCached;
1986 }
1987
1988 return 0;
1989}
1990
1991CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
1992{
1993 if (pwallet == 0)
1994 return 0;
1995
1996 // Must wait until coinbase is safely deep enough in the chain before valuing it
1997 if (IsCoinBase() && GetBlocksToMaturity() > 0)
1998 return 0;
1999
2000 if (fUseCache && fAvailableWatchCreditCached)
2001 return nAvailableWatchCreditCached;
2002
2003 CAmount nCredit = 0;
2004 for (unsigned int i = 0; i < vout.size(); i++)
2005 {
805344dc 2006 if (!pwallet->IsSpent(GetHash(), i))
bbacd882
CF
2007 {
2008 const CTxOut &txout = vout[i];
2009 nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
2010 if (!MoneyRange(nCredit))
2011 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
2012 }
2013 }
2014
2015 nAvailableWatchCreditCached = nCredit;
2016 fAvailableWatchCreditCached = true;
2017 return nCredit;
2018}
2019
2020CAmount CWalletTx::GetChange() const
2021{
2022 if (fChangeCached)
2023 return nChangeCached;
2024 nChangeCached = pwallet->GetChange(*this);
2025 fChangeCached = true;
2026 return nChangeCached;
2027}
2028
2029bool CWalletTx::IsTrusted() const
2030{
2031 // Quick answer in most cases
75a4d512 2032 if (!CheckFinalTx(*this))
bbacd882
CF
2033 return false;
2034 int nDepth = GetDepthInMainChain();
2035 if (nDepth >= 1)
2036 return true;
2037 if (nDepth < 0)
2038 return false;
2039 if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
2040 return false;
2041
2042 // Trusted if all inputs are from us and are in the mempool:
2043 BOOST_FOREACH(const CTxIn& txin, vin)
2044 {
2045 // Transactions not sent by us: not trusted
2046 const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
2047 if (parent == NULL)
2048 return false;
2049 const CTxOut& parentOut = parent->vout[txin.prevout.n];
2050 if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
2051 return false;
2052 }
2053 return true;
2054}
2055
0f5954c4
GA
2056std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
2057{
2058 std::vector<uint256> result;
2059
2060 LOCK(cs_wallet);
2061 // Sort them in chronological order
2062 multimap<unsigned int, CWalletTx*> mapSorted;
2063 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
2064 {
2065 CWalletTx& wtx = item.second;
2066 // Don't rebroadcast if newer than nTime:
2067 if (wtx.nTimeReceived > nTime)
2068 continue;
2069 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
2070 }
2071 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
2072 {
2073 CWalletTx& wtx = *item.second;
2074 if (wtx.RelayWalletTransaction())
805344dc 2075 result.push_back(wtx.GetHash());
0f5954c4
GA
2076 }
2077 return result;
2078}
2079
2080void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
e8ef3da7
WL
2081{
2082 // Do this infrequently and randomly to avoid giving away
2083 // that these are our transactions.
6f252627 2084 if (GetTime() < nNextResend || !fBroadcastTransactions)
e8ef3da7 2085 return;
203d1ae6
LD
2086 bool fFirst = (nNextResend == 0);
2087 nNextResend = GetTime() + GetRand(30 * 60);
e8ef3da7
WL
2088 if (fFirst)
2089 return;
2090
2091 // Only do it if there's been a new block since last time
0f5954c4 2092 if (nBestBlockTime < nLastResend)
e8ef3da7 2093 return;
203d1ae6 2094 nLastResend = GetTime();
e8ef3da7 2095
0f5954c4
GA
2096 // Rebroadcast unconfirmed txes older than 5 minutes before the last
2097 // block was found:
2098 std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60);
2099 if (!relayed.empty())
2100 LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
e8ef3da7
WL
2101}
2102
5b40d886 2103/** @} */ // end of mapWallet
e8ef3da7
WL
2104
2105
2106
2107
5b40d886
MF
2108/** @defgroup Actions
2109 *
2110 * @{
2111 */
e8ef3da7
WL
2112
2113
a372168e 2114CAmount CWallet::GetBalance() const
e8ef3da7 2115{
a372168e 2116 CAmount nTotal = 0;
e8ef3da7 2117 {
55a1db4f 2118 LOCK2(cs_main, cs_wallet);
e8ef3da7
WL
2119 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2120 {
2121 const CWalletTx* pcoin = &(*it).second;
0542619d 2122 if (pcoin->IsTrusted())
8fdb7e10 2123 nTotal += pcoin->GetAvailableCredit();
e8ef3da7
WL
2124 }
2125 }
2126
e8ef3da7
WL
2127 return nTotal;
2128}
2129
a372168e 2130CAmount CWallet::GetUnconfirmedBalance() const
df5ccbd2 2131{
a372168e 2132 CAmount nTotal = 0;
df5ccbd2 2133 {
55a1db4f 2134 LOCK2(cs_main, cs_wallet);
df5ccbd2
WL
2135 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2136 {
2137 const CWalletTx* pcoin = &(*it).second;
75a4d512 2138 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
8fdb7e10 2139 nTotal += pcoin->GetAvailableCredit();
2140 }
2141 }
2142 return nTotal;
2143}
2144
a372168e 2145CAmount CWallet::GetImmatureBalance() const
8fdb7e10 2146{
a372168e 2147 CAmount nTotal = 0;
8fdb7e10 2148 {
55a1db4f 2149 LOCK2(cs_main, cs_wallet);
8fdb7e10 2150 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2151 {
966a0e8c
PK
2152 const CWalletTx* pcoin = &(*it).second;
2153 nTotal += pcoin->GetImmatureCredit();
df5ccbd2
WL
2154 }
2155 }
2156 return nTotal;
2157}
e8ef3da7 2158
a372168e 2159CAmount CWallet::GetWatchOnlyBalance() const
ffd40da3 2160{
a372168e 2161 CAmount nTotal = 0;
ffd40da3 2162 {
39cc4922 2163 LOCK2(cs_main, cs_wallet);
ffd40da3
J
2164 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2165 {
2166 const CWalletTx* pcoin = &(*it).second;
2167 if (pcoin->IsTrusted())
2168 nTotal += pcoin->GetAvailableWatchOnlyCredit();
2169 }
2170 }
870da77d 2171
ffd40da3
J
2172 return nTotal;
2173}
2174
a372168e 2175CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
ffd40da3 2176{
a372168e 2177 CAmount nTotal = 0;
ffd40da3 2178 {
39cc4922 2179 LOCK2(cs_main, cs_wallet);
ffd40da3
J
2180 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2181 {
2182 const CWalletTx* pcoin = &(*it).second;
75a4d512 2183 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
ffd40da3
J
2184 nTotal += pcoin->GetAvailableWatchOnlyCredit();
2185 }
2186 }
2187 return nTotal;
2188}
2189
a372168e 2190CAmount CWallet::GetImmatureWatchOnlyBalance() const
ffd40da3 2191{
a372168e 2192 CAmount nTotal = 0;
ffd40da3 2193 {
39cc4922 2194 LOCK2(cs_main, cs_wallet);
ffd40da3
J
2195 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2196 {
2197 const CWalletTx* pcoin = &(*it).second;
2198 nTotal += pcoin->GetImmatureWatchOnlyCredit();
2199 }
2200 }
2201 return nTotal;
2202}
2203
5b40d886
MF
2204/**
2205 * populate vCoins with vector of available COutputs.
2206 */
0ad6a463 2207uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
bbf5692c 2208uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
0ad6a463 2209
be4f847b 2210void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const
9b0369c7 2211{
5c439232 2212 uint64_t interest,*ptr;
9b0369c7
CM
2213 vCoins.clear();
2214
2215 {
ea3acaf3 2216 LOCK2(cs_main, cs_wallet);
9b0369c7
CM
2217 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2218 {
93a18a36 2219 const uint256& wtxid = it->first;
9b0369c7
CM
2220 const CWalletTx* pcoin = &(*it).second;
2221
75a4d512 2222 if (!CheckFinalTx(*pcoin))
a2709fad
GA
2223 continue;
2224
0542619d 2225 if (fOnlyConfirmed && !pcoin->IsTrusted())
9b0369c7
CM
2226 continue;
2227
2b1cda3b
S
2228 if (pcoin->IsCoinBase() && !fIncludeCoinBase)
2229 continue;
2230
9b0369c7
CM
2231 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
2232 continue;
2233
2b72d46f
GA
2234 int nDepth = pcoin->GetDepthInMainChain();
2235 if (nDepth < 0)
2236 continue;
53dce971 2237
0ad6a463 2238 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2239 {
c8988460 2240 isminetype mine = IsMine(pcoin->vout[i]);
a3e192a3 2241 if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
219953ce 2242 !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) &&
6a86c24d 2243 (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
0ad6a463 2244 {
6ad13d7c 2245 if ( KOMODO_EXCHANGEWALLET == 0 )
0ad6a463 2246 {
6ad13d7c 2247 extern char ASSETCHAINS_SYMBOL[16];
2248 uint32_t locktime; int32_t txheight; CBlockIndex *tipindex;
2249 if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 )
0ad6a463 2250 {
6ad13d7c 2251 if ( pcoin->vout[i].nValue >= 10*COIN )
9d92c93d 2252 {
6ad13d7c 2253 komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue);
2254 if ( (tipindex= chainActive.Tip()) != 0 )
2255 {
2256 interest = komodo_interest(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime);
2257 } else interest = 0;
2258 //interest = komodo_interest(chainActive.Tip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.Tip()->nTime);
2259 if ( interest != 0 )
2260 {
2261 //printf("wallet nValueRet %.8f += interest %.8f ht.%d lock.%u/%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,txheight,locktime,pcoin->nLockTime,tipindex->nTime);
2262 //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.Tip()->nHeight+1,pcoin->nLockTime,chainActive.Tip()->nTime);
2263 //ptr = (uint64_t *)&pcoin->vout[i].nValue;
2264 //(*ptr) += interest;
2265 ptr = (uint64_t *)&pcoin->vout[i].interest;
2266 (*ptr) = interest;
2267 //pcoin->vout[i].nValue += interest;
2268 }
2269 else
2270 {
2271 ptr = (uint64_t *)&pcoin->vout[i].interest;
2272 (*ptr) = 0;
2273 }
e9e8044e 2274 }
258748f5 2275 else
2276 {
2277 ptr = (uint64_t *)&pcoin->vout[i].interest;
2278 (*ptr) = 0;
2279 }
0ad6a463 2280 }
258748f5 2281 else
2282 {
2283 ptr = (uint64_t *)&pcoin->vout[i].interest;
2284 (*ptr) = 0;
2285 }
2286 }
0ad6a463 2287 vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
2288 }
fdbb537d 2289 }
9b0369c7
CM
2290 }
2291 }
2292}
2293
0ad6a463 2294static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
831f59ce
CM
2295{
2296 vector<char> vfIncluded;
2297
2298 vfBest.assign(vValue.size(), true);
2299 nBest = nTotalLower;
2300
907a2aa4
GM
2301 seed_insecure_rand();
2302
831f59ce
CM
2303 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
2304 {
2305 vfIncluded.assign(vValue.size(), false);
a372168e 2306 CAmount nTotal = 0;
831f59ce
CM
2307 bool fReachedTarget = false;
2308 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
2309 {
2310 for (unsigned int i = 0; i < vValue.size(); i++)
2311 {
907a2aa4
GM
2312 //The solver here uses a randomized algorithm,
2313 //the randomness serves no real security purpose but is just
2314 //needed to prevent degenerate behavior and it is important
5b40d886 2315 //that the rng is fast. We do not use a constant random sequence,
907a2aa4
GM
2316 //because there may be some privacy improvement by making
2317 //the selection random.
2318 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
831f59ce
CM
2319 {
2320 nTotal += vValue[i].first;
2321 vfIncluded[i] = true;
2322 if (nTotal >= nTargetValue)
2323 {
2324 fReachedTarget = true;
2325 if (nTotal < nBest)
2326 {
2327 nBest = nTotal;
2328 vfBest = vfIncluded;
2329 }
2330 nTotal -= vValue[i].first;
2331 vfIncluded[i] = false;
2332 }
2333 }
2334 }
2335 }
2336 }
2337}
2338
15649f72 2339bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, uint64_t *interestp) const
e8ef3da7 2340{
6ad13d7c 2341 uint64_t interests[1024],lowest_interest = 0; int32_t count = 0;
e8ef3da7 2342 setCoinsRet.clear();
0f485755 2343 memset(interests,0,sizeof(interests));
e8ef3da7 2344 nValueRet = 0;
15649f72 2345 *interestp = 0;
e8ef3da7 2346 // List of values less than target
a372168e
MF
2347 pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
2348 coinLowestLarger.first = std::numeric_limits<CAmount>::max();
e8ef3da7 2349 coinLowestLarger.second.first = NULL;
a372168e
MF
2350 vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue;
2351 CAmount nTotalLower = 0;
e8ef3da7 2352
e333ab56
CM
2353 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
2354
c8988460 2355 BOOST_FOREACH(const COutput &output, vCoins)
e8ef3da7 2356 {
c8988460
PW
2357 if (!output.fSpendable)
2358 continue;
2359
9b0369c7 2360 const CWalletTx *pcoin = output.tx;
e8ef3da7 2361
a3e192a3 2362 if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
9b0369c7 2363 continue;
e8ef3da7 2364
9b0369c7 2365 int i = output.i;
a372168e 2366 CAmount n = pcoin->vout[i].nValue;
e8ef3da7 2367
a372168e 2368 pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
e8ef3da7 2369
9b0369c7
CM
2370 if (n == nTargetValue)
2371 {
2372 setCoinsRet.insert(coin.second);
2373 nValueRet += coin.first;
6ad13d7c 2374 if ( KOMODO_EXCHANGEWALLET == 0 )
2375 *interestp += pcoin->vout[i].interest;
9b0369c7
CM
2376 return true;
2377 }
2378 else if (n < nTargetValue + CENT)
2379 {
2380 vValue.push_back(coin);
2381 nTotalLower += n;
6ad13d7c 2382 if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) )
d8a120e3 2383 {
9067057a 2384 //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN);
0f485755 2385 interests[count++] = pcoin->vout[i].interest;
d8a120e3 2386 }
9b0369c7
CM
2387 }
2388 else if (n < coinLowestLarger.first)
2389 {
2390 coinLowestLarger = coin;
6ad13d7c 2391 if ( KOMODO_EXCHANGEWALLET == 0 )
2392 lowest_interest = pcoin->vout[i].interest;
e8ef3da7
WL
2393 }
2394 }
2395
831f59ce 2396 if (nTotalLower == nTargetValue)
e8ef3da7 2397 {
c376ac35 2398 for (unsigned int i = 0; i < vValue.size(); ++i)
e8ef3da7
WL
2399 {
2400 setCoinsRet.insert(vValue[i].second);
2401 nValueRet += vValue[i].first;
6ad13d7c 2402 if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
0f485755 2403 *interestp += interests[i];
e8ef3da7
WL
2404 }
2405 return true;
2406 }
2407
831f59ce 2408 if (nTotalLower < nTargetValue)
e8ef3da7
WL
2409 {
2410 if (coinLowestLarger.second.first == NULL)
2411 return false;
2412 setCoinsRet.insert(coinLowestLarger.second);
2413 nValueRet += coinLowestLarger.first;
6ad13d7c 2414 if ( KOMODO_EXCHANGEWALLET == 0 )
2415 *interestp += lowest_interest;
e8ef3da7
WL
2416 return true;
2417 }
2418
e8ef3da7 2419 // Solve subset sum by stochastic approximation
d650f96d 2420 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
831f59ce 2421 vector<char> vfBest;
a372168e 2422 CAmount nBest;
e8ef3da7 2423
831f59ce
CM
2424 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
2425 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
2426 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
e8ef3da7 2427
831f59ce
CM
2428 // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
2429 // or the next bigger coin is closer), return the bigger coin
2430 if (coinLowestLarger.second.first &&
2431 ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
e8ef3da7
WL
2432 {
2433 setCoinsRet.insert(coinLowestLarger.second);
2434 nValueRet += coinLowestLarger.first;
6ad13d7c 2435 if ( KOMODO_EXCHANGEWALLET == 0 )
2436 *interestp += lowest_interest;
e8ef3da7
WL
2437 }
2438 else {
c376ac35 2439 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7
WL
2440 if (vfBest[i])
2441 {
2442 setCoinsRet.insert(vValue[i].second);
2443 nValueRet += vValue[i].first;
6ad13d7c 2444 if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
0f485755 2445 *interestp += interests[i];
e8ef3da7
WL
2446 }
2447
faaeae1e 2448 LogPrint("selectcoins", "SelectCoins() best subset: ");
c376ac35 2449 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7 2450 if (vfBest[i])
f87150f4 2451 LogPrint("selectcoins", "%s + %s, ", FormatMoney(vValue[i].first),FormatMoney(interests[i]));
7d9d134b 2452 LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
e8ef3da7
WL
2453 }
2454
2455 return true;
2456}
2457
29c91a29 2458bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl,uint64_t *interestp) const
e8ef3da7 2459{
2b1cda3b 2460 // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
b82f1051 2461 uint64_t tmp;
2462 if ( interestp == 0 )
2463 interestp = &tmp;
2464 *interestp = 0;
2b1cda3b
S
2465 vector<COutput> vCoinsNoCoinbase, vCoinsWithCoinbase;
2466 AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false);
2467 AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true);
2468 fOnlyCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
2469
2470 // If coinbase utxos can only be sent to zaddrs, exclude any coinbase utxos from coin selection.
2471 bool fProtectCoinbase = Params().GetConsensus().fCoinbaseMustBeProtected;
2472 vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
2473
2474 // Output parameter fNeedCoinbaseCoinsRet is set to true if coinbase utxos need to be spent to meet target amount
2475 if (fProtectCoinbase && vCoinsWithCoinbase.size() > vCoinsNoCoinbase.size()) {
2476 CAmount value = 0;
2477 for (const COutput& out : vCoinsNoCoinbase) {
2478 if (!out.fSpendable) {
2479 continue;
2480 }
2481 value += out.tx->vout[out.i].nValue;
f87150f4 2482 if ( KOMODO_EXCHANGEWALLET == 0 )
2483 value += out.tx->vout[out.i].interest;
2b1cda3b
S
2484 }
2485 if (value <= nTargetValue) {
2486 CAmount valueWithCoinbase = 0;
2487 for (const COutput& out : vCoinsWithCoinbase) {
2488 if (!out.fSpendable) {
2489 continue;
2490 }
2491 valueWithCoinbase += out.tx->vout[out.i].nValue;
f87150f4 2492 if ( KOMODO_EXCHANGEWALLET == 0 )
2493 valueWithCoinbase += out.tx->vout[out.i].interest;
2b1cda3b
S
2494 }
2495 fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
2496 }
2497 }
8726269f 2498 // coin control -> return all selected outputs (we want all to go into the transaction for sure)
6a86c24d
CL
2499 if (coinControl && coinControl->HasSelected())
2500 {
2501 BOOST_FOREACH(const COutput& out, vCoins)
2502 {
2935b211
WL
2503 if(!out.fSpendable)
2504 continue;
6a86c24d 2505 nValueRet += out.tx->vout[out.i].nValue;
6ad13d7c 2506 if ( KOMODO_EXCHANGEWALLET == 0 )
2507 *interestp += out.tx->vout[out.i].interest;
6a86c24d
CL
2508 setCoinsRet.insert(make_pair(out.tx, out.i));
2509 }
2510 return (nValueRet >= nTargetValue);
2511 }
38dfbe15 2512//fprintf(stderr,"nValueRet %8f vs target %.8f\n",(double)nValueRet/COIN,(double)nTargetValue/COIN);
15649f72 2513 return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet,interestp) ||
2514 SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet,interestp) ||
2515 (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet,interestp)));
e8ef3da7
WL
2516}
2517
292623ad
CL
2518bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend,
2519 CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl)
e8ef3da7 2520{
b8adc564 2521 uint64_t interest2,interest = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0;
292623ad 2522 BOOST_FOREACH (const CRecipient& recipient, vecSend)
e8ef3da7 2523 {
292623ad 2524 if (nValue < 0 || recipient.nAmount < 0)
1f00f4e9
GA
2525 {
2526 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 2527 return false;
1f00f4e9 2528 }
292623ad
CL
2529 nValue += recipient.nAmount;
2530
2531 if (recipient.fSubtractFeeFromAmount)
2532 nSubtractFeeFromAmount++;
e8ef3da7
WL
2533 }
2534 if (vecSend.empty() || nValue < 0)
1f00f4e9
GA
2535 {
2536 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 2537 return false;
1f00f4e9 2538 }
e8ef3da7 2539
b33d1f5e 2540 wtxNew.fTimeReceivedIsTxTime = true;
4c6e2295 2541 wtxNew.BindWallet(this);
4949004d 2542 CMutableTransaction txNew;
e8ef3da7 2543
e19d8b3d 2544 if ( 0 )
2545 {
2546 // Discourage fee sniping.
2547 //
2548 // However because of a off-by-one-error in previous versions we need to
2549 // neuter it by setting nLockTime to at least one less than nBestHeight.
2550 // Secondly currently propagation of transactions created for block heights
2551 // corresponding to blocks that were just mined may be iffy - transactions
2552 // aren't re-accepted into the mempool - we additionally neuter the code by
2553 // going ten blocks back. Doesn't yet do anything for sniping, but does act
2554 // to shake out wallet bugs like not showing nLockTime'd transactions at
2555 // all.
2556 txNew.nLockTime = std::max(0, chainActive.Height() - 10);
2557
2558 // Secondly occasionally randomly pick a nLockTime even further back, so
2559 // that transactions that are delayed after signing for whatever reason,
2560 // e.g. high-latency mix networks and some CoinJoin implementations, have
2561 // better privacy.
2562 if (GetRandInt(10) == 0)
2563 txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
2564
2565 assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
2566 assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
2567 }
2568 else
2569 {
c3e43fb1 2570 txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now
e19d8b3d 2571 }
ba7fcc8d 2572
e8ef3da7 2573 {
f8dcd5ca 2574 LOCK2(cs_main, cs_wallet);
e8ef3da7 2575 {
c1c9d5b4 2576 nFeeRet = 0;
050d2e95 2577 while (true)
e8ef3da7 2578 {
4949004d
PW
2579 txNew.vin.clear();
2580 txNew.vout.clear();
e8ef3da7 2581 wtxNew.fFromMe = true;
292623ad
CL
2582 nChangePosRet = -1;
2583 bool fFirst = true;
e8ef3da7 2584
292623ad
CL
2585 CAmount nTotalValue = nValue;
2586 if (nSubtractFeeFromAmount == 0)
2587 nTotalValue += nFeeRet;
e8ef3da7
WL
2588 double dPriority = 0;
2589 // vouts to the payees
292623ad 2590 BOOST_FOREACH (const CRecipient& recipient, vecSend)
8de9bb53 2591 {
292623ad
CL
2592 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
2593
2594 if (recipient.fSubtractFeeFromAmount)
2595 {
2596 txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
2597
2598 if (fFirst) // first receiver pays the remainder not divisible by output count
2599 {
2600 fFirst = false;
2601 txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
2602 }
2603 }
2604
13fc83c7 2605 if (txout.IsDust(::minRelayTxFee))
1f00f4e9 2606 {
292623ad
CL
2607 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
2608 {
2609 if (txout.nValue < 0)
2610 strFailReason = _("The transaction amount is too small to pay the fee");
2611 else
2612 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
2613 }
2614 else
2615 strFailReason = _("Transaction amount too small");
8de9bb53 2616 return false;
1f00f4e9 2617 }
4949004d 2618 txNew.vout.push_back(txout);
8de9bb53 2619 }
e8ef3da7
WL
2620
2621 // Choose coins to use
2622 set<pair<const CWalletTx*,unsigned int> > setCoins;
a372168e 2623 CAmount nValueIn = 0;
2b1cda3b
S
2624 bool fOnlyCoinbaseCoins = false;
2625 bool fNeedCoinbaseCoins = false;
b8adc564 2626 interest = interest2 = 0;
29c91a29 2627 if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl,&interest))
1f00f4e9 2628 {
2b1cda3b
S
2629 if (fOnlyCoinbaseCoins && Params().GetConsensus().fCoinbaseMustBeProtected) {
2630 strFailReason = _("Coinbase funds can only be sent to a zaddr");
2631 } else if (fNeedCoinbaseCoins) {
2632 strFailReason = _("Insufficient funds, coinbase funds can only be spent after they have been sent to a zaddr");
2633 } else {
2634 strFailReason = _("Insufficient funds");
2635 }
e8ef3da7 2636 return false;
1f00f4e9 2637 }
e8ef3da7
WL
2638 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
2639 {
a372168e 2640 CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
2d9b0b7f 2641 //The coin age after the next block (depth+1) is used instead of the current,
d7836552
GM
2642 //reflecting an assumption the user would accept a bit more delay for
2643 //a chance at a free transaction.
2d9b0b7f 2644 //But mempool inputs might still be in the mempool, so their age stays 0
38dfbe15 2645 //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN);
6ad13d7c 2646 if ( KOMODO_EXCHANGEWALLET == 0 )
2647 interest2 += pcoin.first->vout[pcoin.second].interest;
2d9b0b7f
AM
2648 int age = pcoin.first->GetDepthInMainChain();
2649 if (age != 0)
2650 age += 1;
2651 dPriority += (double)nCredit * age;
e8ef3da7 2652 }
6ad13d7c 2653 if ( KOMODO_EXCHANGEWALLET != 0 )
a7785a1c 2654 {
2626c7e3 2655 //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN);
6ad13d7c 2656 interest = 0;
a7785a1c 2657 }
8726269f 2658 CAmount nChange = (nValueIn - nValue + interest);
0c053c9e 2659fprintf(stderr,"wallet change %.8f (%.8f - %.8f) interest %.8f total %.8f\n",(double)nChange/COIN,(double)nValueIn/COIN,(double)nValue/COIN,(double)interest/COIN,(double)nTotalValue/COIN);
292623ad
CL
2660 if (nSubtractFeeFromAmount == 0)
2661 nChange -= nFeeRet;
a7dd11c6
PW
2662
2663 if (nChange > 0)
e8ef3da7 2664 {
bf798734
GA
2665 // Fill a vout to ourself
2666 // TODO: pass in scriptChange instead of reservekey so
2667 // change transaction isn't always pay-to-bitcoin-address
e8ef3da7 2668 CScript scriptChange;
6a86c24d
CL
2669
2670 // coin control: send change to custom address
2671 if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
0be990ba 2672 scriptChange = GetScriptForDestination(coinControl->destChange);
6a86c24d
CL
2673
2674 // no coin control: send change to newly generated address
2675 else
2676 {
2677 // Note: We use a new key here to keep it from being obvious which side is the change.
2678 // The drawback is that by not reusing a previous key, the change may be lost if a
2679 // backup is restored, if the backup doesn't have the new private key for the change.
2680 // If we reused the old key, it would be possible to add code to look for and
2681 // rediscover unknown transactions that were written with keys of ours to recover
2682 // post-backup change.
2683
2684 // Reserve a new key pair from key pool
2685 CPubKey vchPubKey;
3ec03ada 2686 extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
2687 if ( USE_EXTERNAL_PUBKEY == 0 )
2688 {
2689 //fprintf(stderr,"use notary pubkey\n");
2690 //scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
2691 bool ret;
2692 ret = reservekey.GetReservedKey(vchPubKey);
2693 assert(ret); // should never fail, as we just unlocked
2694 scriptChange = GetScriptForDestination(vchPubKey.GetID());
2695 }
2696 else
2697 {
2698 scriptChange = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
2699 }
6a86c24d 2700 }
e8ef3da7 2701
8de9bb53
GA
2702 CTxOut newTxOut(nChange, scriptChange);
2703
292623ad
CL
2704 // We do not move dust-change to fees, because the sender would end up paying more than requested.
2705 // This would be against the purpose of the all-inclusive feature.
2706 // So instead we raise the change and deduct from the recipient.
2707 if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee))
2708 {
2709 CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue;
2710 newTxOut.nValue += nDust; // raise change until no more dust
2711 for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
2712 {
2713 if (vecSend[i].fSubtractFeeFromAmount)
2714 {
2715 txNew.vout[i].nValue -= nDust;
2716 if (txNew.vout[i].IsDust(::minRelayTxFee))
2717 {
2718 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
2719 return false;
2720 }
2721 break;
2722 }
2723 }
2724 }
2725
8de9bb53
GA
2726 // Never create dust outputs; if we would, just
2727 // add the dust to the fee.
13fc83c7 2728 if (newTxOut.IsDust(::minRelayTxFee))
8de9bb53
GA
2729 {
2730 nFeeRet += nChange;
2731 reservekey.ReturnKey();
2732 }
2733 else
2734 {
429dabb5 2735 nChangePosRet = txNew.vout.size() - 1; // dont change first or last
292623ad 2736 vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
4949004d 2737 txNew.vout.insert(position, newTxOut);
8de9bb53 2738 }
f38345e9 2739 } else reservekey.ReturnKey();
e8ef3da7
WL
2740
2741 // Fill vin
ba7fcc8d
PT
2742 //
2743 // Note how the sequence number is set to max()-1 so that the
2744 // nLockTime set above actually works.
e8ef3da7 2745 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
805344dc 2746 txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
ba7fcc8d 2747 std::numeric_limits<unsigned int>::max()-1));
e8ef3da7
WL
2748
2749 // Sign
2750 int nIn = 0;
2751 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
4949004d 2752 if (!SignSignature(*this, *coin.first, txNew, nIn++))
1f00f4e9
GA
2753 {
2754 strFailReason = _("Signing transaction failed");
e8ef3da7 2755 return false;
1f00f4e9 2756 }
e8ef3da7 2757
4949004d
PW
2758 // Embed the constructed transaction data in wtxNew.
2759 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
2760
e8ef3da7 2761 // Limit size
6b6aaa16 2762 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
74f15a73 2763 if (nBytes >= MAX_TX_SIZE)
1f00f4e9
GA
2764 {
2765 strFailReason = _("Transaction too large");
e8ef3da7 2766 return false;
1f00f4e9 2767 }
4d707d51 2768 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
e8ef3da7 2769
aa279d61
GM
2770 // Can we complete this as a free transaction?
2771 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
2772 {
2773 // Not enough fee: enough priority?
2774 double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
2775 // Not enough mempool history to estimate: use hard-coded AllowFree.
2776 if (dPriorityNeeded <= 0 && AllowFree(dPriority))
2777 break;
2778
2779 // Small enough, and priority high enough, to send for free
2780 if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
2781 break;
2782 }
b33d1f5e 2783
aa279d61 2784 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
b33d1f5e 2785
aa279d61
GM
2786 // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
2787 // because we must be at the maximum allowed fee.
2788 if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
e8ef3da7 2789 {
aa279d61
GM
2790 strFailReason = _("Transaction too large for fee policy");
2791 return false;
e8ef3da7
WL
2792 }
2793
aa279d61
GM
2794 if (nFeeRet >= nFeeNeeded)
2795 break; // Done, enough fee included.
b33d1f5e
GA
2796
2797 // Include more fee and try again.
2798 nFeeRet = nFeeNeeded;
2799 continue;
e8ef3da7
WL
2800 }
2801 }
2802 }
e8ef3da7 2803
292623ad 2804 return true;
e8ef3da7
WL
2805}
2806
5b40d886
MF
2807/**
2808 * Call after CreateTransaction unless you want to abort
2809 */
e8ef3da7
WL
2810bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
2811{
e8ef3da7 2812 {
f8dcd5ca 2813 LOCK2(cs_main, cs_wallet);
7d9d134b 2814 LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
e8ef3da7
WL
2815 {
2816 // This is only to keep the database open to defeat the auto-flush for the
2817 // duration of this scope. This is the only place where this optimization
2818 // maybe makes sense; please don't do it anywhere else.
44bc988e 2819 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
e8ef3da7
WL
2820
2821 // Take key pair from key pool so it won't be used again
2822 reservekey.KeepKey();
2823
2824 // Add tx to wallet, because if it has change it's also ours,
2825 // otherwise just for transaction history.
44bc988e 2826 AddToWallet(wtxNew, false, pwalletdb);
e8ef3da7 2827
93a18a36 2828 // Notify that old coins are spent
e8ef3da7
WL
2829 set<CWalletTx*> setCoins;
2830 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
2831 {
2832 CWalletTx &coin = mapWallet[txin.prevout.hash];
4c6e2295 2833 coin.BindWallet(this);
805344dc 2834 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
e8ef3da7
WL
2835 }
2836
2837 if (fFileBacked)
2838 delete pwalletdb;
2839 }
2840
2841 // Track how many getdata requests our transaction gets
805344dc 2842 mapRequestCount[wtxNew.GetHash()] = 0;
e8ef3da7 2843
6f252627 2844 if (fBroadcastTransactions)
e8ef3da7 2845 {
6f252627
WL
2846 // Broadcast
2847 if (!wtxNew.AcceptToMemoryPool(false))
2848 {
68c266b2 2849 fprintf(stderr,"commit failed\n");
2850 // This must not fail. The transaction has already been signed and recorded.
7ff9d122 2851 LogPrintf("CommitTransaction(): Error: Transaction not valid\n");
6f252627
WL
2852 return false;
2853 }
2854 wtxNew.RelayWalletTransaction();
e8ef3da7 2855 }
e8ef3da7 2856 }
e8ef3da7
WL
2857 return true;
2858}
2859
a372168e 2860CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
b33d1f5e
GA
2861{
2862 // payTxFee is user-set "I want to pay this much"
a372168e 2863 CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
c1c9d5b4
CL
2864 // user selected total at least (default=true)
2865 if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK())
2866 nFeeNeeded = payTxFee.GetFeePerK();
b33d1f5e
GA
2867 // User didn't set: use -txconfirmtarget to estimate...
2868 if (nFeeNeeded == 0)
2869 nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
2870 // ... unless we don't have enough mempool data, in which case fall
2871 // back to a hard-coded fee
2872 if (nFeeNeeded == 0)
13fc83c7 2873 nFeeNeeded = minTxFee.GetFee(nTxBytes);
aa279d61
GM
2874 // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
2875 if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
2876 nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
2877 // But always obey the maximum
2878 if (nFeeNeeded > maxTxFee)
2879 nFeeNeeded = maxTxFee;
b33d1f5e
GA
2880 return nFeeNeeded;
2881}
2882
e8ef3da7
WL
2883
2884
2885
eed1785f 2886DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
e8ef3da7
WL
2887{
2888 if (!fFileBacked)
4f76be1d 2889 return DB_LOAD_OK;
e8ef3da7 2890 fFirstRunRet = false;
eed1785f 2891 DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
d764d916 2892 if (nLoadWalletRet == DB_NEED_REWRITE)
9e9869d0 2893 {
d764d916
GA
2894 if (CDB::Rewrite(strWalletFile, "\x04pool"))
2895 {
012ca1c9 2896 LOCK(cs_wallet);
d764d916
GA
2897 setKeyPool.clear();
2898 // Note: can't top-up keypool here, because wallet is locked.
2899 // User will be prompted to unlock wallet the next operation
c6de7c35 2900 // that requires a new key.
d764d916 2901 }
9e9869d0
PW
2902 }
2903
7ec55267
MC
2904 if (nLoadWalletRet != DB_LOAD_OK)
2905 return nLoadWalletRet;
fd61d6f5 2906 fFirstRunRet = !vchDefaultKey.IsValid();
e8ef3da7 2907
39278369
CL
2908 uiInterface.LoadWallet(this);
2909
116df55e 2910 return DB_LOAD_OK;
e8ef3da7
WL
2911}
2912
ae3d0aba 2913
77cbd462 2914DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
518f3bda
JG
2915{
2916 if (!fFileBacked)
2917 return DB_LOAD_OK;
77cbd462 2918 DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx);
518f3bda
JG
2919 if (nZapWalletTxRet == DB_NEED_REWRITE)
2920 {
2921 if (CDB::Rewrite(strWalletFile, "\x04pool"))
2922 {
2923 LOCK(cs_wallet);
2924 setKeyPool.clear();
2925 // Note: can't top-up keypool here, because wallet is locked.
2926 // User will be prompted to unlock wallet the next operation
5b40d886 2927 // that requires a new key.
518f3bda
JG
2928 }
2929 }
2930
2931 if (nZapWalletTxRet != DB_LOAD_OK)
2932 return nZapWalletTxRet;
2933
2934 return DB_LOAD_OK;
2935}
2936
2937
a41d5fe0 2938bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
ae3d0aba 2939{
ca4cf5cf
GA
2940 bool fUpdated = false;
2941 {
2942 LOCK(cs_wallet); // mapAddressBook
2943 std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
2944 fUpdated = mi != mapAddressBook.end();
2945 mapAddressBook[address].name = strName;
2946 if (!strPurpose.empty()) /* update purpose only if requested */
2947 mapAddressBook[address].purpose = strPurpose;
2948 }
8d657a65 2949 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
ca4cf5cf 2950 strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
ae3d0aba
WL
2951 if (!fFileBacked)
2952 return false;
a41d5fe0
GA
2953 if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
2954 return false;
10254401 2955 return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
ae3d0aba
WL
2956}
2957
a41d5fe0 2958bool CWallet::DelAddressBook(const CTxDestination& address)
ae3d0aba 2959{
b10e1470 2960 {
ca4cf5cf
GA
2961 LOCK(cs_wallet); // mapAddressBook
2962
2963 if(fFileBacked)
b10e1470 2964 {
ca4cf5cf
GA
2965 // Delete destdata tuples associated with address
2966 std::string strAddress = CBitcoinAddress(address).ToString();
2967 BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
2968 {
2969 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
2970 }
b10e1470 2971 }
ca4cf5cf 2972 mapAddressBook.erase(address);
b10e1470
WL
2973 }
2974
8d657a65 2975 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
ca4cf5cf 2976
ae3d0aba
WL
2977 if (!fFileBacked)
2978 return false;
a41d5fe0 2979 CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
10254401 2980 return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
ae3d0aba
WL
2981}
2982
fd61d6f5 2983bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
ae3d0aba
WL
2984{
2985 if (fFileBacked)
2986 {
2987 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
2988 return false;
2989 }
2990 vchDefaultKey = vchPubKey;
2991 return true;
2992}
2993
5b40d886
MF
2994/**
2995 * Mark old keypool keys as used,
2996 * and generate all new keys
2997 */
37971fcc
GA
2998bool CWallet::NewKeyPool()
2999{
37971fcc 3000 {
f8dcd5ca 3001 LOCK(cs_wallet);
37971fcc 3002 CWalletDB walletdb(strWalletFile);
51ed9ec9 3003 BOOST_FOREACH(int64_t nIndex, setKeyPool)
37971fcc
GA
3004 walletdb.ErasePool(nIndex);
3005 setKeyPool.clear();
3006
3007 if (IsLocked())
3008 return false;
3009
51ed9ec9 3010 int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
37971fcc
GA
3011 for (int i = 0; i < nKeys; i++)
3012 {
51ed9ec9 3013 int64_t nIndex = i+1;
37971fcc
GA
3014 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
3015 setKeyPool.insert(nIndex);
3016 }
f48742c2 3017 LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
37971fcc
GA
3018 }
3019 return true;
3020}
3021
13dd2d09 3022bool CWallet::TopUpKeyPool(unsigned int kpSize)
e8ef3da7 3023{
e8ef3da7 3024 {
f8dcd5ca
PW
3025 LOCK(cs_wallet);
3026
4e87d341
MC
3027 if (IsLocked())
3028 return false;
3029
e8ef3da7
WL
3030 CWalletDB walletdb(strWalletFile);
3031
3032 // Top up key pool
13dd2d09
JG
3033 unsigned int nTargetSize;
3034 if (kpSize > 0)
3035 nTargetSize = kpSize;
3036 else
51ed9ec9 3037 nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
13dd2d09 3038
faf705a4 3039 while (setKeyPool.size() < (nTargetSize + 1))
e8ef3da7 3040 {
51ed9ec9 3041 int64_t nEnd = 1;
e8ef3da7
WL
3042 if (!setKeyPool.empty())
3043 nEnd = *(--setKeyPool.end()) + 1;
3044 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
5262fde0 3045 throw runtime_error("TopUpKeyPool(): writing generated key failed");
e8ef3da7 3046 setKeyPool.insert(nEnd);
783b182c 3047 LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
e8ef3da7 3048 }
4e87d341
MC
3049 }
3050 return true;
3051}
3052
51ed9ec9 3053void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
4e87d341
MC
3054{
3055 nIndex = -1;
fd61d6f5 3056 keypool.vchPubKey = CPubKey();
4e87d341 3057 {
f8dcd5ca
PW
3058 LOCK(cs_wallet);
3059
4e87d341
MC
3060 if (!IsLocked())
3061 TopUpKeyPool();
e8ef3da7
WL
3062
3063 // Get the oldest key
4e87d341
MC
3064 if(setKeyPool.empty())
3065 return;
3066
3067 CWalletDB walletdb(strWalletFile);
3068
e8ef3da7
WL
3069 nIndex = *(setKeyPool.begin());
3070 setKeyPool.erase(setKeyPool.begin());
3071 if (!walletdb.ReadPool(nIndex, keypool))
5262fde0 3072 throw runtime_error("ReserveKeyFromKeyPool(): read failed");
fd61d6f5 3073 if (!HaveKey(keypool.vchPubKey.GetID()))
5262fde0 3074 throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
fd61d6f5 3075 assert(keypool.vchPubKey.IsValid());
36a65612 3076 //LogPrintf("keypool reserve %d\n", nIndex);
e8ef3da7
WL
3077 }
3078}
3079
51ed9ec9 3080void CWallet::KeepKey(int64_t nIndex)
e8ef3da7
WL
3081{
3082 // Remove from key pool
3083 if (fFileBacked)
3084 {
3085 CWalletDB walletdb(strWalletFile);
6cc4a62c 3086 walletdb.ErasePool(nIndex);
e8ef3da7 3087 }
f48742c2 3088 LogPrintf("keypool keep %d\n", nIndex);
e8ef3da7
WL
3089}
3090
51ed9ec9 3091void CWallet::ReturnKey(int64_t nIndex)
e8ef3da7
WL
3092{
3093 // Return to key pool
f8dcd5ca
PW
3094 {
3095 LOCK(cs_wallet);
e8ef3da7 3096 setKeyPool.insert(nIndex);
f8dcd5ca 3097 }
36a65612 3098 //LogPrintf("keypool return %d\n", nIndex);
e8ef3da7
WL
3099}
3100
71ac5052 3101bool CWallet::GetKeyFromPool(CPubKey& result)
e8ef3da7 3102{
51ed9ec9 3103 int64_t nIndex = 0;
e8ef3da7 3104 CKeyPool keypool;
7db3b75b 3105 {
f8dcd5ca 3106 LOCK(cs_wallet);
ed02c95d
GA
3107 ReserveKeyFromKeyPool(nIndex, keypool);
3108 if (nIndex == -1)
7db3b75b 3109 {
ed02c95d
GA
3110 if (IsLocked()) return false;
3111 result = GenerateNewKey();
7db3b75b
GA
3112 return true;
3113 }
ed02c95d
GA
3114 KeepKey(nIndex);
3115 result = keypool.vchPubKey;
7db3b75b 3116 }
7db3b75b 3117 return true;
e8ef3da7
WL
3118}
3119
51ed9ec9 3120int64_t CWallet::GetOldestKeyPoolTime()
e8ef3da7 3121{
51ed9ec9 3122 int64_t nIndex = 0;
e8ef3da7
WL
3123 CKeyPool keypool;
3124 ReserveKeyFromKeyPool(nIndex, keypool);
4e87d341
MC
3125 if (nIndex == -1)
3126 return GetTime();
e8ef3da7
WL
3127 ReturnKey(nIndex);
3128 return keypool.nTime;
3129}
3130
a372168e 3131std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
22dfd735 3132{
a372168e 3133 map<CTxDestination, CAmount> balances;
22dfd735 3134
3135 {
3136 LOCK(cs_wallet);
3137 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
3138 {
3139 CWalletTx *pcoin = &walletEntry.second;
3140
75a4d512 3141 if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
22dfd735 3142 continue;
3143
3144 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
3145 continue;
3146
3147 int nDepth = pcoin->GetDepthInMainChain();
a3e192a3 3148 if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
22dfd735 3149 continue;
3150
b1093efa 3151 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 3152 {
b1093efa 3153 CTxDestination addr;
22dfd735 3154 if (!IsMine(pcoin->vout[i]))
3155 continue;
b1093efa
GM
3156 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
3157 continue;
22dfd735 3158
a372168e 3159 CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
22dfd735 3160
22dfd735 3161 if (!balances.count(addr))
3162 balances[addr] = 0;
3163 balances[addr] += n;
3164 }
3165 }
3166 }
3167
3168 return balances;
3169}
3170
b1093efa 3171set< set<CTxDestination> > CWallet::GetAddressGroupings()
22dfd735 3172{
95691680 3173 AssertLockHeld(cs_wallet); // mapWallet
b1093efa
GM
3174 set< set<CTxDestination> > groupings;
3175 set<CTxDestination> grouping;
22dfd735 3176
3177 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
3178 {
3179 CWalletTx *pcoin = &walletEntry.second;
3180
a3fad211 3181 if (pcoin->vin.size() > 0)
22dfd735 3182 {
a3fad211 3183 bool any_mine = false;
22dfd735 3184 // group all input addresses with each other
3185 BOOST_FOREACH(CTxIn txin, pcoin->vin)
b1093efa
GM
3186 {
3187 CTxDestination address;
a3fad211
GM
3188 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
3189 continue;
b1093efa
GM
3190 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
3191 continue;
3192 grouping.insert(address);
a3fad211 3193 any_mine = true;
b1093efa 3194 }
22dfd735 3195
3196 // group change with input addresses
a3fad211
GM
3197 if (any_mine)
3198 {
3199 BOOST_FOREACH(CTxOut txout, pcoin->vout)
3200 if (IsChange(txout))
3201 {
3202 CTxDestination txoutAddr;
3203 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
3204 continue;
3205 grouping.insert(txoutAddr);
3206 }
3207 }
3208 if (grouping.size() > 0)
3209 {
3210 groupings.insert(grouping);
3211 grouping.clear();
3212 }
22dfd735 3213 }
3214
3215 // group lone addrs by themselves
b1093efa 3216 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 3217 if (IsMine(pcoin->vout[i]))
3218 {
b1093efa
GM
3219 CTxDestination address;
3220 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
3221 continue;
3222 grouping.insert(address);
22dfd735 3223 groupings.insert(grouping);
3224 grouping.clear();
3225 }
3226 }
3227
b1093efa
GM
3228 set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
3229 map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
3230 BOOST_FOREACH(set<CTxDestination> grouping, groupings)
22dfd735 3231 {
3232 // make a set of all the groups hit by this new group
b1093efa
GM
3233 set< set<CTxDestination>* > hits;
3234 map< CTxDestination, set<CTxDestination>* >::iterator it;
3235 BOOST_FOREACH(CTxDestination address, grouping)
22dfd735 3236 if ((it = setmap.find(address)) != setmap.end())
3237 hits.insert((*it).second);
3238
3239 // merge all hit groups into a new single group and delete old groups
b1093efa
GM
3240 set<CTxDestination>* merged = new set<CTxDestination>(grouping);
3241 BOOST_FOREACH(set<CTxDestination>* hit, hits)
22dfd735 3242 {
3243 merged->insert(hit->begin(), hit->end());
3244 uniqueGroupings.erase(hit);
3245 delete hit;
3246 }
3247 uniqueGroupings.insert(merged);
3248
3249 // update setmap
b1093efa 3250 BOOST_FOREACH(CTxDestination element, *merged)
22dfd735 3251 setmap[element] = merged;
3252 }
3253
b1093efa
GM
3254 set< set<CTxDestination> > ret;
3255 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
22dfd735 3256 {
3257 ret.insert(*uniqueGrouping);
3258 delete uniqueGrouping;
3259 }
3260
3261 return ret;
3262}
3263
3624356e
GA
3264set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
3265{
43422a01 3266 LOCK(cs_wallet);
3624356e
GA
3267 set<CTxDestination> result;
3268 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
3269 {
3270 const CTxDestination& address = item.first;
3271 const string& strName = item.second.name;
3272 if (strName == strAccount)
3273 result.insert(address);
3274 }
3275 return result;
3276}
3277
360cfe14 3278bool CReserveKey::GetReservedKey(CPubKey& pubkey)
e8ef3da7
WL
3279{
3280 if (nIndex == -1)
3281 {
3282 CKeyPool keypool;
3283 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
0d7b28e5
MC
3284 if (nIndex != -1)
3285 vchPubKey = keypool.vchPubKey;
360cfe14 3286 else {
6c37f7fd 3287 return false;
cee69980 3288 }
e8ef3da7 3289 }
fd61d6f5 3290 assert(vchPubKey.IsValid());
360cfe14
PW
3291 pubkey = vchPubKey;
3292 return true;
e8ef3da7
WL
3293}
3294
3295void CReserveKey::KeepKey()
3296{
3297 if (nIndex != -1)
3298 pwallet->KeepKey(nIndex);
3299 nIndex = -1;
fd61d6f5 3300 vchPubKey = CPubKey();
e8ef3da7
WL
3301}
3302
3303void CReserveKey::ReturnKey()
3304{
3305 if (nIndex != -1)
3306 pwallet->ReturnKey(nIndex);
3307 nIndex = -1;
fd61d6f5 3308 vchPubKey = CPubKey();
e8ef3da7 3309}
ae3d0aba 3310
434e4273 3311void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
30ab2c9c
PW
3312{
3313 setAddress.clear();
3314
3315 CWalletDB walletdb(strWalletFile);
3316
f8dcd5ca 3317 LOCK2(cs_main, cs_wallet);
51ed9ec9 3318 BOOST_FOREACH(const int64_t& id, setKeyPool)
30ab2c9c
PW
3319 {
3320 CKeyPool keypool;
3321 if (!walletdb.ReadPool(id, keypool))
5262fde0 3322 throw runtime_error("GetAllReserveKeyHashes(): read failed");
fd61d6f5 3323 assert(keypool.vchPubKey.IsValid());
10254401
PW
3324 CKeyID keyID = keypool.vchPubKey.GetID();
3325 if (!HaveKey(keyID))
5262fde0 3326 throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
10254401 3327 setAddress.insert(keyID);
30ab2c9c
PW
3328 }
3329}
fe4a6550
WL
3330
3331void CWallet::UpdatedTransaction(const uint256 &hashTx)
3332{
3333 {
3334 LOCK(cs_wallet);
3335 // Only notify UI if this transaction is in this wallet
3336 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
3337 if (mi != mapWallet.end())
3338 NotifyTransactionChanged(this, hashTx, CT_UPDATED);
3339 }
3340}
fdbb537d
JG
3341
3342void CWallet::LockCoin(COutPoint& output)
3343{
95691680 3344 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
3345 setLockedCoins.insert(output);
3346}
3347
3348void CWallet::UnlockCoin(COutPoint& output)
3349{
95691680 3350 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
3351 setLockedCoins.erase(output);
3352}
3353
3354void CWallet::UnlockAllCoins()
3355{
95691680 3356 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
3357 setLockedCoins.clear();
3358}
3359
3360bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
3361{
95691680 3362 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
3363 COutPoint outpt(hash, n);
3364
3365 return (setLockedCoins.count(outpt) > 0);
3366}
3367
3368void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
3369{
95691680 3370 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
3371 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
3372 it != setLockedCoins.end(); it++) {
3373 COutPoint outpt = (*it);
3374 vOutpts.push_back(outpt);
3375 }
3376}
3377
5b40d886 3378/** @} */ // end of Actions
8b59a3d3 3379
3380class CAffectedKeysVisitor : public boost::static_visitor<void> {
3381private:
3382 const CKeyStore &keystore;
3383 std::vector<CKeyID> &vKeys;
3384
3385public:
3386 CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
3387
3388 void Process(const CScript &script) {
3389 txnouttype type;
3390 std::vector<CTxDestination> vDest;
3391 int nRequired;
3392 if (ExtractDestinations(script, type, vDest, nRequired)) {
3393 BOOST_FOREACH(const CTxDestination &dest, vDest)
3394 boost::apply_visitor(*this, dest);
3395 }
3396 }
3397
3398 void operator()(const CKeyID &keyId) {
3399 if (keystore.HaveKey(keyId))
3400 vKeys.push_back(keyId);
3401 }
3402
3403 void operator()(const CScriptID &scriptId) {
3404 CScript script;
3405 if (keystore.GetCScript(scriptId, script))
3406 Process(script);
3407 }
3408
3409 void operator()(const CNoDestination &none) {}
3410};
3411
51ed9ec9 3412void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
95691680 3413 AssertLockHeld(cs_wallet); // mapKeyMetadata
434e4273
PW
3414 mapKeyBirth.clear();
3415
3416 // get birth times for keys with metadata
3417 for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
3418 if (it->second.nCreateTime)
3419 mapKeyBirth[it->first] = it->second.nCreateTime;
3420
3421 // map in which we'll infer heights of other keys
4c6d41b8 3422 CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
434e4273
PW
3423 std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
3424 std::set<CKeyID> setKeys;
3425 GetKeys(setKeys);
3426 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
3427 if (mapKeyBirth.count(keyid) == 0)
3428 mapKeyFirstBlock[keyid] = pindexMax;
3429 }
3430 setKeys.clear();
3431
3432 // if there are no such keys, we're done
3433 if (mapKeyFirstBlock.empty())
3434 return;
3435
3436 // find first block that affects those keys, if there are any left
3437 std::vector<CKeyID> vAffected;
3438 for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
3439 // iterate over all wallet transactions...
3440 const CWalletTx &wtx = (*it).second;
145d5be8 3441 BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
4c6d41b8 3442 if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
434e4273
PW
3443 // ... which are already in a block
3444 int nHeight = blit->second->nHeight;
3445 BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
3446 // iterate over all their outputs
8b59a3d3 3447 CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
434e4273
PW
3448 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
3449 // ... and all their affected keys
3450 std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
3451 if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
3452 rit->second = blit->second;
3453 }
3454 vAffected.clear();
3455 }
3456 }
3457 }
3458
3459 // Extract block timestamps for those keys
3460 for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
209377a7 3461 mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
434e4273 3462}
b10e1470
WL
3463
3464bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
3465{
8476d5d4
CL
3466 if (boost::get<CNoDestination>(&dest))
3467 return false;
3468
b10e1470
WL
3469 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
3470 if (!fFileBacked)
3471 return true;
3472 return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
3473}
3474
3475bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
3476{
3477 if (!mapAddressBook[dest].destdata.erase(key))
3478 return false;
3479 if (!fFileBacked)
3480 return true;
3481 return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
3482}
3483
3484bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
3485{
3486 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
3487 return true;
3488}
3489
3490bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
3491{
3492 std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
3493 if(i != mapAddressBook.end())
3494 {
3495 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
3496 if(j != i->second.destdata.end())
3497 {
3498 if(value)
3499 *value = j->second;
3500 return true;
3501 }
3502 }
3503 return false;
3504}
af8297c0
WL
3505
3506CKeyPool::CKeyPool()
3507{
3508 nTime = GetTime();
3509}
3510
3511CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
3512{
3513 nTime = GetTime();
3514 vchPubKey = vchPubKeyIn;
3515}
3516
3517CWalletKey::CWalletKey(int64_t nExpires)
3518{
3519 nTimeCreated = (nExpires ? GetTime() : 0);
3520 nTimeExpires = nExpires;
3521}
0101483f 3522
4b0deb3b 3523int CMerkleTx::SetMerkleBranch(const CBlock& block)
0101483f
WL
3524{
3525 AssertLockHeld(cs_main);
3526 CBlock blockTmp;
3527
4b0deb3b
DK
3528 // Update the tx's hashBlock
3529 hashBlock = block.GetHash();
0101483f 3530
4b0deb3b
DK
3531 // Locate the transaction
3532 for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
3533 if (block.vtx[nIndex] == *(CTransaction*)this)
3534 break;
3535 if (nIndex == (int)block.vtx.size())
3536 {
3537 vMerkleBranch.clear();
3538 nIndex = -1;
5262fde0 3539 LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
4b0deb3b 3540 return 0;
0101483f
WL
3541 }
3542
4b0deb3b
DK
3543 // Fill in merkle branch
3544 vMerkleBranch = block.GetMerkleBranch(nIndex);
3545
0101483f 3546 // Is the tx in a block that's in the main chain
145d5be8 3547 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
0101483f
WL
3548 if (mi == mapBlockIndex.end())
3549 return 0;
4b0deb3b 3550 const CBlockIndex* pindex = (*mi).second;
0101483f
WL
3551 if (!pindex || !chainActive.Contains(pindex))
3552 return 0;
3553
3554 return chainActive.Height() - pindex->nHeight + 1;
3555}
3556
a31e8bad 3557int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
0101483f 3558{
4f152496 3559 if (hashBlock.IsNull() || nIndex == -1)
0101483f
WL
3560 return 0;
3561 AssertLockHeld(cs_main);
3562
3563 // Find the block it claims to be in
145d5be8 3564 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
0101483f
WL
3565 if (mi == mapBlockIndex.end())
3566 return 0;
3567 CBlockIndex* pindex = (*mi).second;
3568 if (!pindex || !chainActive.Contains(pindex))
3569 return 0;
3570
3571 // Make sure the merkle branch connects to this block
3572 if (!fMerkleVerified)
3573 {
805344dc 3574 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
0101483f
WL
3575 return 0;
3576 fMerkleVerified = true;
3577 }
3578
3579 pindexRet = pindex;
3580 return chainActive.Height() - pindex->nHeight + 1;
3581}
3582
a31e8bad 3583int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
0101483f
WL
3584{
3585 AssertLockHeld(cs_main);
3586 int nResult = GetDepthInMainChainINTERNAL(pindexRet);
805344dc 3587 if (nResult == 0 && !mempool.exists(GetHash()))
0101483f
WL
3588 return -1; // Not in chain, not in mempool
3589
3590 return nResult;
3591}
3592
3593int CMerkleTx::GetBlocksToMaturity() const
3594{
7a90b9dd 3595 extern char ASSETCHAINS_SYMBOL[];
3596 if ( ASSETCHAINS_SYMBOL[0] == 0 )
3597 COINBASE_MATURITY = _COINBASE_MATURITY;
0101483f
WL
3598 if (!IsCoinBase())
3599 return 0;
3600 return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
3601}
3602
3603
1371e6f5 3604bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
0101483f
WL
3605{
3606 CValidationState state;
1371e6f5 3607 return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
0101483f
WL
3608}
3609
cb0d208f
S
3610/**
3611 * Find notes in the wallet filtered by payment address, min depth and ability to spend.
3612 * These notes are decrypted and added to the output parameter vector, outEntries.
3613 */
3614void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent)
a5ac2e25
S
3615{
3616 bool fFilterAddress = false;
3617 libzcash::PaymentAddress filterPaymentAddress;
3618 if (address.length() > 0) {
3619 filterPaymentAddress = CZCPaymentAddress(address).Get();
3620 fFilterAddress = true;
3621 }
3622
3623 LOCK2(cs_main, cs_wallet);
3624
3625 for (auto & p : mapWallet) {
3626 CWalletTx wtx = p.second;
3627
3628 // Filter the transactions before checking for notes
3629 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < minDepth) {
3630 continue;
3631 }
3632
dec49d1f 3633 if (wtx.mapNoteData.size() == 0) {
a5ac2e25
S
3634 continue;
3635 }
3636
dec49d1f 3637 for (auto & pair : wtx.mapNoteData) {
a5ac2e25
S
3638 JSOutPoint jsop = pair.first;
3639 CNoteData nd = pair.second;
3640 PaymentAddress pa = nd.address;
3641
3642 // skip notes which belong to a different payment address in the wallet
3643 if (fFilterAddress && !(pa == filterPaymentAddress)) {
3644 continue;
3645 }
3646
3647 // skip note which has been spent
1a62587e 3648 if (ignoreSpent && nd.nullifier && IsSpent(*nd.nullifier)) {
a5ac2e25
S
3649 continue;
3650 }
3651
3652 int i = jsop.js; // Index into CTransaction.vjoinsplit
3653 int j = jsop.n; // Index into JSDescription.ciphertexts
3654
3655 // Get cached decryptor
3656 ZCNoteDecryption decryptor;
3657 if (!GetNoteDecryptor(pa, decryptor)) {
3658 // Note decryptors are created when the wallet is loaded, so it should always exist
3659 throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", CZCPaymentAddress(pa).ToString()));
3660 }
3661
3662 // determine amount of funds in the note
3663 auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
3664 try {
3665 NotePlaintext plaintext = NotePlaintext::decrypt(
3666 decryptor,
3667 wtx.vjoinsplit[i].ciphertexts[j],
3668 wtx.vjoinsplit[i].ephemeralKey,
3669 hSig,
3670 (unsigned char) j);
3671
3672 outEntries.push_back(CNotePlaintextEntry{jsop, plaintext});
3673
3674 } catch (const std::exception &) {
3675 // Couldn't decrypt with this spending key
3676 throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString()));
3677 }
3678 }
3679 }
3680}
This page took 1.019145 seconds and 4 git commands to generate.