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