]> Git Repo - VerusCoin.git/blob - src/wallet/wallet.cpp
Fix advanced, multi-currency operators and UTXO selection
[VerusCoin.git] / src / wallet / wallet.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
5
6 #include "wallet/wallet.h"
7
8 #include "asyncrpcqueue.h"
9 #include "checkpoints.h"
10 #include "coincontrol.h"
11 #include "core_io.h"
12 #include "consensus/upgrades.h"
13 #include "consensus/validation.h"
14 #include "consensus/consensus.h"
15 #include "init.h"
16 #include "key_io.h"
17 #include "main.h"
18 #include "mmr.h"
19 #include "net.h"
20 #include "rpc/protocol.h"
21 #include "rpc/server.h"
22 #include "script/script.h"
23 #include "script/sign.h"
24 #include "timedata.h"
25 #include "utilmoneystr.h"
26 #include "zcash/Note.hpp"
27 #include "crypter.h"
28 #include "coins.h"
29 #include "wallet/asyncrpcoperation_saplingmigration.h"
30 #include "zcash/zip32.h"
31 #include "cc/StakeGuard.h"
32 #include "pbaas/identity.h"
33 #include "pbaas/pbaas.h"
34
35 #include <assert.h>
36
37 #include <boost/algorithm/string/replace.hpp>
38 #include <boost/filesystem.hpp>
39 #include <boost/thread.hpp>
40
41 using namespace std;
42 using namespace libzcash;
43
44 /**
45  * Settings
46  */
47 CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
48 CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
49 unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
50 bool bSpendZeroConfChange = true;
51 bool fSendFreeTransactions = false;
52 bool fPayAtLeastCustomFee = true;
53 #include "komodo_defs.h"
54
55 extern int32_t USE_EXTERNAL_PUBKEY;
56 extern std::string NOTARY_PUBKEY;
57 extern int32_t KOMODO_EXCHANGEWALLET;
58 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
59 extern uint160 ASSETCHAINS_CHAINID;
60 extern int32_t VERUS_MIN_STAKEAGE;
61 CBlockIndex *komodo_chainactive(int32_t height);
62 extern std::string DONATION_PUBKEY;
63 extern BlockMap mapBlockIndex;
64
65 /**
66  * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
67  * Override with -mintxfee
68  */
69 CFeeRate CWallet::minTxFee = CFeeRate(1000);
70
71 /** @defgroup mapWallet
72  *
73  * @{
74  */
75
76 struct CompareValueOnly
77 {
78     bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
79                     const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
80     {
81         return t1.first < t2.first;
82     }
83 };
84
85 class CompareValueMap
86 {
87 public:
88     CCurrencyValueMap totalTargetValues;
89     CompareValueMap() {}
90     CompareValueMap(const CCurrencyValueMap &targetValues) : totalTargetValues(targetValues) {}
91     bool CompareMaps(const CCurrencyValueMap &m1,
92                      const CCurrencyValueMap &m2) const
93     {
94         // if we have a target to compare against,
95         // check to see if one leaves less change after meeting the target
96         if (totalTargetValues.valueMap.size())
97         {
98             CCurrencyValueMap leftover1 = m1.SubtractToZero(totalTargetValues);
99             CCurrencyValueMap leftover2 = m2.SubtractToZero(totalTargetValues);
100
101             if (leftover1 < leftover2 && leftover2 < leftover1)
102             {
103                 if (leftover1.valueMap.size() < leftover2.valueMap.size())
104                 {
105                     return true;
106                 }
107                 else if (leftover2.valueMap.size() < leftover1.valueMap.size())
108                 {
109                     return false;
110                 }
111             }
112             return leftover1 < leftover2;
113         }
114         else if (m1 < m2 && m2 < m1)
115         {
116             // this is used for sorting
117             // what we care about most in this case is that we always give the same answer,
118             // so, run a repeatable check, regardless of the order of operands. we'd also want
119             // to be as close to right as possible.
120             CCurrencyValueMap checkMap1 = m1.IntersectingValues(m2);
121             CCurrencyValueMap checkMap2;
122             // where they intersect, they are empty, no way to know which is less for sorting
123             if (!(checkMap2 < checkMap1))
124             {
125                 return false;
126             }
127             checkMap2 = checkMap1 - m2.IntersectingValues(m1);
128             CAmount total = 0;
129             for (auto &oneCur : checkMap2.valueMap)
130             {
131                 total += oneCur.second;
132             }
133             if (total < 0)
134             {
135                 return true;
136             }
137             else
138             {
139                 return false;
140             }
141         }
142         return m1 < m2;
143     }
144 };
145
146 std::string JSOutPoint::ToString() const
147 {
148     return strprintf("JSOutPoint(%s, %d, %d)", hash.ToString().substr(0,10), js, n);
149 }
150
151 std::string COutput::ToString() const
152 {
153     return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
154 }
155
156 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
157 {
158     LOCK(cs_wallet);
159     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
160     if (it == mapWallet.end())
161         return NULL;
162     return &(it->second);
163 }
164
165 // Generate a new spending key and return its public payment address
166 libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey()
167 {
168     AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
169
170     auto k = SproutSpendingKey::random();
171     auto addr = k.address();
172
173     // Check for collision, even though it is unlikely to ever occur
174     if (CCryptoKeyStore::HaveSproutSpendingKey(addr))
175         throw std::runtime_error("CWallet::GenerateNewSproutZKey(): Collision detected");
176
177     // Create new metadata
178     int64_t nCreationTime = GetTime();
179     mapSproutZKeyMetadata[addr] = CKeyMetadata(nCreationTime);
180
181     if (!AddSproutZKey(k))
182         throw std::runtime_error("CWallet::GenerateNewSproutZKey(): AddSproutZKey failed");
183     return addr;
184 }
185
186 // Generate a new Sapling spending key and return its public payment address
187 SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
188 {
189     AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
190
191     // Create new metadata
192     int64_t nCreationTime = GetTime();
193     CKeyMetadata metadata(nCreationTime);
194
195     // Try to get the seed
196     HDSeed seed;
197     if (!GetHDSeed(seed))
198         throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
199
200     auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
201     uint32_t bip44CoinType = Params().BIP44CoinType();
202
203     // We use a fixed keypath scheme of m/32'/coin_type'/account'
204     // Derive m/32'
205     auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
206     // Derive m/32'/coin_type'
207     auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT);
208
209     // Derive account key at next index, skip keys already known to the wallet
210     libzcash::SaplingExtendedSpendingKey xsk;
211     do
212     {
213         xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT);
214         metadata.hdKeypath = "m/32'/" + std::to_string(bip44CoinType) + "'/" + std::to_string(hdChain.saplingAccountCounter) + "'";
215         metadata.seedFp = hdChain.seedFp;
216         // Increment childkey index
217         hdChain.saplingAccountCounter++;
218     } while (HaveSaplingSpendingKey(xsk.expsk.full_viewing_key()));
219
220     // Update the chain model in the database
221     if (fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(hdChain))
222         throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Writing HD chain model failed");
223
224     auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
225     mapSaplingZKeyMetadata[ivk] = metadata;
226
227     auto addr = xsk.DefaultAddress();
228     if (!AddSaplingZKey(xsk, addr)) {
229         throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
230     }
231     // return default sapling payment address.
232     return addr;
233 }
234
235 // Add spending key to keystore 
236 bool CWallet::AddSaplingZKey(
237     const libzcash::SaplingExtendedSpendingKey &sk,
238     const libzcash::SaplingPaymentAddress &defaultAddr)
239 {
240     AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
241
242     if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
243         return false;
244     }
245     
246     if (!fFileBacked) {
247         return true;
248     }
249
250     if (!IsCrypted()) {
251         auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
252         return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
253     }
254     
255     return true;
256 }
257
258 // Add payment address -> incoming viewing key map entry
259 bool CWallet::AddSaplingIncomingViewingKey(
260     const libzcash::SaplingIncomingViewingKey &ivk,
261     const libzcash::SaplingPaymentAddress &addr)
262 {
263     AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
264
265     if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
266         return false;
267     }
268
269     if (!fFileBacked) {
270         return true;
271     }
272
273     if (!IsCrypted()) {
274         return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
275     }
276
277     return true;
278 }
279
280
281 // Add spending key to keystore and persist to disk
282 bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key)
283 {
284     AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
285     auto addr = key.address();
286
287     if (!CCryptoKeyStore::AddSproutSpendingKey(key))
288         return false;
289
290     // check if we need to remove from viewing keys
291     if (HaveSproutViewingKey(addr))
292         RemoveSproutViewingKey(key.viewing_key());
293
294     if (!fFileBacked)
295         return true;
296
297     if (!IsCrypted()) {
298         return CWalletDB(strWalletFile).WriteZKey(addr,
299                                                   key,
300                                                   mapSproutZKeyMetadata[addr]);
301     }
302     return true;
303 }
304
305 CPubKey CWallet::GenerateNewKey()
306 {
307     AssertLockHeld(cs_wallet); // mapKeyMetadata
308     bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
309
310     CKey secret;
311     secret.MakeNewKey(fCompressed);
312
313     // Compressed public keys were introduced in version 0.6.0
314     if (fCompressed)
315         SetMinVersion(FEATURE_COMPRPUBKEY);
316
317     CPubKey pubkey = secret.GetPubKey();
318     assert(secret.VerifyPubKey(pubkey));
319
320     // Create new metadata
321     int64_t nCreationTime = GetTime();
322     mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
323     if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
324         nTimeFirstKey = nCreationTime;
325
326     if (!AddKeyPubKey(secret, pubkey))
327         throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
328     return pubkey;
329 }
330
331 bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
332 {
333     AssertLockHeld(cs_wallet); // mapKeyMetadata
334     if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
335         return false;
336
337     // check if we need to remove from watch-only
338     CScript script;
339     script = GetScriptForDestination(pubkey.GetID());
340     if (HaveWatchOnly(script))
341         RemoveWatchOnly(script);
342
343     if (!fFileBacked)
344         return true;
345     if (!IsCrypted()) {
346         return CWalletDB(strWalletFile).WriteKey(pubkey,
347                                                  secret.GetPrivKey(),
348                                                  mapKeyMetadata[pubkey.GetID()]);
349     }
350     return true;
351 }
352
353 bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
354                             const vector<unsigned char> &vchCryptedSecret)
355 {
356
357     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
358         return false;
359     if (!fFileBacked)
360         return true;
361     {
362         LOCK(cs_wallet);
363         if (pwalletdbEncryption)
364             return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
365                                                         vchCryptedSecret,
366                                                         mapKeyMetadata[vchPubKey.GetID()]);
367         else
368             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
369                                                             vchCryptedSecret,
370                                                             mapKeyMetadata[vchPubKey.GetID()]);
371     }
372     return false;
373 }
374
375
376 bool CWallet::AddCryptedSproutSpendingKey(
377     const libzcash::SproutPaymentAddress &address,
378     const libzcash::ReceivingKey &rk,
379     const std::vector<unsigned char> &vchCryptedSecret)
380 {
381     if (!CCryptoKeyStore::AddCryptedSproutSpendingKey(address, rk, vchCryptedSecret))
382         return false;
383     if (!fFileBacked)
384         return true;
385     {
386         LOCK(cs_wallet);
387         if (pwalletdbEncryption) {
388             return pwalletdbEncryption->WriteCryptedZKey(address,
389                                                          rk,
390                                                          vchCryptedSecret,
391                                                          mapSproutZKeyMetadata[address]);
392         } else {
393             return CWalletDB(strWalletFile).WriteCryptedZKey(address,
394                                                              rk,
395                                                              vchCryptedSecret,
396                                                              mapSproutZKeyMetadata[address]);
397         }
398     }
399     return false;
400 }
401
402 bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
403                                            const std::vector<unsigned char> &vchCryptedSecret,
404                                            const libzcash::SaplingPaymentAddress &defaultAddr)
405 {
406     if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
407         return false;
408     if (!fFileBacked)
409         return true;
410     {
411         LOCK(cs_wallet);
412         if (pwalletdbEncryption) {
413             return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
414                                                          vchCryptedSecret,
415                                                          mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
416         } else {
417             return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
418                                                          vchCryptedSecret,
419                                                          mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
420         }
421     }
422     return false;
423 }
424
425 bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
426 {
427     AssertLockHeld(cs_wallet); // mapKeyMetadata
428     if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
429         nTimeFirstKey = meta.nCreateTime;
430
431     mapKeyMetadata[pubkey.GetID()] = meta;
432     return true;
433 }
434
435 bool CWallet::LoadZKeyMetadata(const SproutPaymentAddress &addr, const CKeyMetadata &meta)
436 {
437     AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
438     mapSproutZKeyMetadata[addr] = meta;
439     return true;
440 }
441
442 bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
443 {
444     return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
445 }
446
447 bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret)
448 {
449     return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret);
450 }
451
452 bool CWallet::LoadCryptedSaplingZKey(
453     const libzcash::SaplingExtendedFullViewingKey &extfvk,
454     const std::vector<unsigned char> &vchCryptedSecret)
455 {
456      return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
457 }
458
459 bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
460 {
461     AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
462     mapSaplingZKeyMetadata[ivk] = meta;
463     return true;
464 }
465
466 bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
467 {
468     return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
469 }
470
471 bool CWallet::LoadSaplingPaymentAddress(
472     const libzcash::SaplingPaymentAddress &addr,
473     const libzcash::SaplingIncomingViewingKey &ivk)
474 {
475     return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
476 }
477
478 bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
479 {
480     return CCryptoKeyStore::AddSproutSpendingKey(key);
481 }
482
483 bool CWallet::AddSproutViewingKey(const libzcash::SproutViewingKey &vk)
484 {
485     if (!CCryptoKeyStore::AddSproutViewingKey(vk)) {
486         return false;
487     }
488     nTimeFirstKey = 1; // No birthday information for viewing keys.
489     if (!fFileBacked) {
490         return true;
491     }
492     return CWalletDB(strWalletFile).WriteSproutViewingKey(vk);
493 }
494
495 bool CWallet::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk)
496 {
497     AssertLockHeld(cs_wallet);
498     if (!CCryptoKeyStore::RemoveSproutViewingKey(vk)) {
499         return false;
500     }
501     if (fFileBacked) {
502         if (!CWalletDB(strWalletFile).EraseSproutViewingKey(vk)) {
503             return false;
504         }
505     }
506
507     return true;
508 }
509
510 bool CWallet::LoadSproutViewingKey(const libzcash::SproutViewingKey &vk)
511 {
512     return CCryptoKeyStore::AddSproutViewingKey(vk);
513 }
514
515 bool CWallet::AddCScript(const CScript& redeemScript)
516 {
517     // if this is an identity, which we currently need to check, we
518     // store the ID as a script in the wallet script storage, but instead of using the
519     // hash of the script, we store it under the name ID
520     if (!CCryptoKeyStore::AddCScript(redeemScript))
521         return false;
522     if (!fFileBacked)
523         return true;
524     return CWalletDB(strWalletFile).WriteCScript(ScriptOrIdentityID(redeemScript), redeemScript);
525 }
526
527 bool CWallet::LoadCScript(const CScript& redeemScript)
528 {
529     /* A sanity check was added in pull #3843 to avoid adding redeemScripts
530      * that never can be redeemed. However, old wallets may still contain
531      * these. Do not add them to the wallet and warn. */
532     if (redeemScript.size() > CScript::MAX_SCRIPT_ELEMENT_SIZE)
533     {
534         std::string strAddr = EncodeDestination(ScriptOrIdentityID(redeemScript));
535         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",
536             __func__, redeemScript.size(), CScript::MAX_SCRIPT_ELEMENT_SIZE, strAddr);
537         return true;
538     }
539
540     return CCryptoKeyStore::AddCScript(redeemScript);
541 }
542
543 bool CWallet::AddIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
544 {
545     // if this is an identity, which we currently need to check, we
546     // store the ID as a script in the wallet script storage, but instead of using the
547     // hash of the script, we store it under the name ID
548     if (!CCryptoKeyStore::AddIdentity(mapKey, identity))
549         return false;
550     if (!fFileBacked)
551         return true;
552     return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
553 }
554
555 bool CWallet::UpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
556 {
557     // if this is an identity, which we currently need to check, we
558     // store the ID as a script in the wallet script storage, but instead of using the
559     // hash of the script, we store it under the name ID
560     if (!CCryptoKeyStore::UpdateIdentity(mapKey, identity))
561         return false;
562     if (!fFileBacked)
563         return true;
564     return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
565 }
566
567 bool CWallet::AddUpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
568 {
569     // if this is an identity, which we currently need to check, we
570     // store the ID as a script in the wallet script storage, but instead of using the
571     // hash of the script, we store it under the name ID
572     if (!CCryptoKeyStore::AddUpdateIdentity(mapKey, identity))
573         return false;
574     if (!fFileBacked)
575         return true;
576     return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
577 }
578
579 void CWallet::ClearIdentities()
580 {
581     if (fFileBacked)
582     {
583         for (auto idPair : mapIdentities)
584         {
585             CWalletDB(strWalletFile).EraseIdentity(idPair.first);
586         }    
587     }
588
589     CCryptoKeyStore::ClearIdentities();
590 }
591
592 bool CWallet::RemoveIdentity(const CIdentityMapKey &mapKey, const uint256 &txid)
593 {
594     CIdentityMapKey localKey = mapKey;
595     std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> toErase;
596     if (localKey.blockHeight == 0)
597     {
598         localKey.blockHeight = INT_MAX;
599     }
600     if (!GetIdentity(mapKey, localKey, toErase))
601     {
602         return false;
603     }
604     if (!txid.IsNull())
605     {
606         std::pair<CIdentityMapKey, CIdentityMapValue> idEntry;
607         for (auto id : toErase)
608         {
609             if (id.second.txid == txid)
610             {
611                 idEntry = id;
612             }
613         }
614         toErase.clear();
615         if (idEntry.first.IsValid() && idEntry.second.IsValid())
616         {
617             toErase.push_back(idEntry);
618         }
619     }
620     if (!CCryptoKeyStore::RemoveIdentity(mapKey, txid))
621         return false;
622     if (!fFileBacked)
623         return true;
624
625     bool error = false;
626     for (auto idPair : toErase)
627     {
628         error = CWalletDB(strWalletFile).EraseIdentity(idPair.first) ? error : true;
629     }    
630     return error;
631 }
632
633 bool CWallet::LoadIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
634 {
635     return CCryptoKeyStore::AddUpdateIdentity(mapKey, identity);
636 }
637
638 // returns all key IDs that are destinations for UTXOs in the wallet
639 std::set<CKeyID> CWallet::GetTransactionDestinationIDs()
640 {
641     std::vector<COutput> vecOutputs;
642     std::set<CKeyID> setKeyIDs;
643
644     AvailableCoins(vecOutputs, false, NULL, true, true, true, true);
645
646     for (int i = 0; i < vecOutputs.size(); i++)
647     {
648         auto &txout = vecOutputs[i];
649         txnouttype outType;
650         std::vector<CTxDestination> dests;
651         int nRequiredSigs;
652
653         if (ExtractDestinations(txout.tx->vout[txout.i].scriptPubKey, outType, dests, nRequiredSigs))
654         {
655             CScript scriptPubKey;
656             if (outType != TX_SCRIPTHASH ||
657                 (dests.size() &&
658                  GetCScript(GetDestinationID(dests[0]), scriptPubKey) &&
659                  ExtractDestinations(scriptPubKey, outType, dests, nRequiredSigs)))
660             {
661                 for (auto &dest : dests)
662                 {
663                     if (dest.which() == COptCCParams::ADDRTYPE_PK || dest.which() == COptCCParams::ADDRTYPE_PKH)
664                     {
665                         setKeyIDs.insert(GetDestinationID(dest));
666                     }
667                 }
668             }
669         }
670     }
671     return setKeyIDs;
672 }
673
674 bool CWallet::AddWatchOnly(const CScript &dest)
675 {
676     if (!CCryptoKeyStore::AddWatchOnly(dest))
677         return false;
678     nTimeFirstKey = 1; // No birthday information for watch-only keys.
679     NotifyWatchonlyChanged(true);
680     if (!fFileBacked)
681         return true;
682     return CWalletDB(strWalletFile).WriteWatchOnly(dest);
683 }
684
685 bool CWallet::RemoveWatchOnly(const CScript &dest)
686 {
687     AssertLockHeld(cs_wallet);
688     if (!CCryptoKeyStore::RemoveWatchOnly(dest))
689         return false;
690     if (!HaveWatchOnly())
691         NotifyWatchonlyChanged(false);
692     if (fFileBacked)
693         if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
694             return false;
695
696     return true;
697 }
698
699 bool CWallet::LoadWatchOnly(const CScript &dest)
700 {
701     return CCryptoKeyStore::AddWatchOnly(dest);
702 }
703
704 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
705 {
706     CCrypter crypter;
707     CKeyingMaterial vMasterKey;
708
709     {
710         LOCK(cs_wallet);
711         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
712         {
713             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
714                 return false;
715             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
716                 continue; // try another master key
717             if (CCryptoKeyStore::Unlock(vMasterKey)) {
718                 // Now that the wallet is decrypted, ensure we have an HD seed.
719                 // https://github.com/zcash/zcash/issues/3607
720                 if (!this->HaveHDSeed()) {
721                     this->GenerateNewSeed();
722                 }
723                 return true;
724             }
725         }
726     }
727     return false;
728 }
729
730 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
731 {
732     bool fWasLocked = IsLocked();
733
734     {
735         LOCK(cs_wallet);
736         Lock();
737
738         CCrypter crypter;
739         CKeyingMaterial vMasterKey;
740         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
741         {
742             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
743                 return false;
744             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
745                 return false;
746             if (CCryptoKeyStore::Unlock(vMasterKey))
747             {
748                 int64_t nStartTime = GetTimeMillis();
749                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
750                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
751
752                 nStartTime = GetTimeMillis();
753                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
754                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
755
756                 if (pMasterKey.second.nDeriveIterations < 25000)
757                     pMasterKey.second.nDeriveIterations = 25000;
758
759                 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
760
761                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
762                     return false;
763                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
764                     return false;
765                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
766                 if (fWasLocked)
767                     Lock();
768                 return true;
769             }
770         }
771     }
772
773     return false;
774 }
775
776 void CWallet::ChainTipAdded(const CBlockIndex *pindex,
777                             const CBlock *pblock,
778                             SproutMerkleTree sproutTree,
779                             SaplingMerkleTree saplingTree)
780 {
781     IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree);
782     UpdateSaplingNullifierNoteMapForBlock(pblock);
783 }
784
785 void CWallet::ChainTip(const CBlockIndex *pindex, 
786                        const CBlock *pblock,
787                        SproutMerkleTree sproutTree,
788                        SaplingMerkleTree saplingTree, 
789                        bool added)
790 {
791     if (added) {
792         ChainTipAdded(pindex, pblock, sproutTree, saplingTree);
793         // Prevent migration transactions from being created when node is syncing after launch,
794         // and also when node wakes up from suspension/hibernation and incoming blocks are old.
795         if (!IsInitialBlockDownload(Params()) &&
796             pblock->GetBlockTime() > GetAdjustedTime() - 3 * 60 * 60)
797         {
798             RunSaplingMigration(pindex->GetHeight());
799         }
800     } else {
801         DecrementNoteWitnesses(pindex);
802         UpdateSaplingNullifierNoteMapForBlock(pblock);
803     }
804 }
805
806 void CWallet::RunSaplingMigration(int blockHeight) {
807     if (!Params().GetConsensus().NetworkUpgradeActive(blockHeight, Consensus::UPGRADE_SAPLING)) {
808         return;
809     }
810     LOCK(cs_wallet);
811     if (!fSaplingMigrationEnabled) {
812         return;
813     }
814     // The migration transactions to be sent in a particular batch can take
815     // significant time to generate, and this time depends on the speed of the user's
816     // computer. If they were generated only after a block is seen at the target
817     // height minus 1, then this could leak information. Therefore, for target
818     // height N, implementations SHOULD start generating the transactions at around
819     // height N-5
820     if (blockHeight % 500 == 495) {
821         std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
822         std::shared_ptr<AsyncRPCOperation> lastOperation = q->getOperationForId(saplingMigrationOperationId);
823         if (lastOperation != nullptr) {
824             lastOperation->cancel();
825         }
826         pendingSaplingMigrationTxs.clear();
827         std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_saplingmigration(blockHeight + 5));
828         saplingMigrationOperationId = operation->getId();
829         q->addOperation(operation);
830     } else if (blockHeight % 500 == 499) {
831         std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
832         std::shared_ptr<AsyncRPCOperation> lastOperation = q->getOperationForId(saplingMigrationOperationId);
833         if (lastOperation != nullptr) {
834             lastOperation->cancel();
835         }
836         for (const CTransaction& transaction : pendingSaplingMigrationTxs) {
837             // Send the transaction
838             CWalletTx wtx(this, transaction);
839             CommitTransaction(wtx, boost::none);
840         }
841         pendingSaplingMigrationTxs.clear();
842     }
843 }
844
845 void CWallet::AddPendingSaplingMigrationTx(const CTransaction& tx) {
846     LOCK(cs_wallet);
847     pendingSaplingMigrationTxs.push_back(tx);
848 }
849
850 void CWallet::SetBestChain(const CBlockLocator& loc)
851 {
852     CWalletDB walletdb(strWalletFile);
853     SetBestChainINTERNAL(walletdb, loc);
854 }
855
856 std::set<std::pair<libzcash::PaymentAddress, uint256>> CWallet::GetNullifiersForAddresses(
857         const std::set<libzcash::PaymentAddress> & addresses)
858 {
859     std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet;
860     // Sapling ivk -> list of addrs map
861     // (There may be more than one diversified address for a given ivk.)
862     std::map<libzcash::SaplingIncomingViewingKey, std::vector<libzcash::SaplingPaymentAddress>> ivkMap;
863     for (const auto & addr : addresses) {
864         auto saplingAddr = boost::get<libzcash::SaplingPaymentAddress>(&addr);
865         if (saplingAddr != nullptr) {
866             libzcash::SaplingIncomingViewingKey ivk;
867             this->GetSaplingIncomingViewingKey(*saplingAddr, ivk);
868             ivkMap[ivk].push_back(*saplingAddr);
869         }
870     }
871     for (const auto & txPair : mapWallet) {
872         // Sprout
873         for (const auto & noteDataPair : txPair.second.mapSproutNoteData) {
874             auto & noteData = noteDataPair.second;
875             auto & nullifier = noteData.nullifier;
876             auto & address = noteData.address;
877             if (nullifier && addresses.count(address)) {
878                 nullifierSet.insert(std::make_pair(address, nullifier.get()));
879             }
880         }
881         // Sapling
882         for (const auto & noteDataPair : txPair.second.mapSaplingNoteData) {
883             auto & noteData = noteDataPair.second;
884             auto & nullifier = noteData.nullifier;
885             auto & ivk = noteData.ivk;
886             if (nullifier && ivkMap.count(ivk)) {
887                 for (const auto & addr : ivkMap[ivk]) {
888                     nullifierSet.insert(std::make_pair(addr, nullifier.get()));
889                 }
890             }
891         }
892     }
893     return nullifierSet;
894 }
895
896 bool CWallet::IsNoteSproutChange(
897         const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
898         const PaymentAddress & address,
899         const JSOutPoint & jsop)
900 {
901     // A Note is marked as "change" if the address that received it
902     // also spent Notes in the same transaction. This will catch,
903     // for instance:
904     // - Change created by spending fractions of Notes (because
905     //   z_sendmany sends change to the originating z-address).
906     // - "Chaining Notes" used to connect JoinSplits together.
907     // - Notes created by consolidation transactions (e.g. using
908     //   z_mergetoaddress).
909     // - Notes sent from one address to itself.
910     for (const JSDescription & jsd : mapWallet[jsop.hash].vJoinSplit) {
911         for (const uint256 & nullifier : jsd.nullifiers) {
912             if (nullifierSet.count(std::make_pair(address, nullifier))) {
913                 return true;
914             }
915         }
916     }
917     return false;
918 }
919
920 bool CWallet::IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
921         const libzcash::PaymentAddress & address,
922         const SaplingOutPoint & op)
923 {
924     // A Note is marked as "change" if the address that received it
925     // also spent Notes in the same transaction. This will catch,
926     // for instance:
927     // - Change created by spending fractions of Notes (because
928     //   z_sendmany sends change to the originating z-address).
929     // - Notes created by consolidation transactions (e.g. using
930     //   z_mergetoaddress).
931     // - Notes sent from one address to itself.
932     for (const SpendDescription &spend : mapWallet[op.hash].vShieldedSpend) {
933         if (nullifierSet.count(std::make_pair(address, spend.nullifier))) {
934             return true;
935         }
936     }
937     return false;
938 }
939
940 bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
941 {
942     LOCK(cs_wallet); // nWalletVersion
943     if (nWalletVersion >= nVersion)
944         return true;
945
946     // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
947     if (fExplicit && nVersion > nWalletMaxVersion)
948             nVersion = FEATURE_LATEST;
949
950     nWalletVersion = nVersion;
951
952     if (nVersion > nWalletMaxVersion)
953         nWalletMaxVersion = nVersion;
954
955     if (fFileBacked)
956     {
957         CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
958         if (nWalletVersion > 40000)
959             pwalletdb->WriteMinVersion(nWalletVersion);
960         if (!pwalletdbIn)
961             delete pwalletdb;
962     }
963
964     return true;
965 }
966
967 bool CWallet::SetMaxVersion(int nVersion)
968 {
969     LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
970     // cannot downgrade below current version
971     if (nWalletVersion > nVersion)
972         return false;
973
974     nWalletMaxVersion = nVersion;
975
976     return true;
977 }
978
979 set<uint256> CWallet::GetConflicts(const uint256& txid) const
980 {
981     set<uint256> result;
982     AssertLockHeld(cs_wallet);
983
984     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
985     if (it == mapWallet.end())
986         return result;
987     const CWalletTx& wtx = it->second;
988
989     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
990
991     BOOST_FOREACH(const CTxIn& txin, wtx.vin)
992     {
993         if (mapTxSpends.count(txin.prevout) <= 1)
994             continue;  // No conflict if zero or one spends
995         range = mapTxSpends.equal_range(txin.prevout);
996         for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
997             result.insert(it->second);
998     }
999
1000     std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
1001
1002     for (const JSDescription& jsdesc : wtx.vJoinSplit) {
1003         for (const uint256& nullifier : jsdesc.nullifiers) {
1004             if (mapTxSproutNullifiers.count(nullifier) <= 1) {
1005                 continue;  // No conflict if zero or one spends
1006             }
1007             range_n = mapTxSproutNullifiers.equal_range(nullifier);
1008             for (TxNullifiers::const_iterator it = range_n.first; it != range_n.second; ++it) {
1009                 result.insert(it->second);
1010             }
1011         }
1012     }
1013
1014     std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_o;
1015
1016     for (const SpendDescription &spend : wtx.vShieldedSpend) {
1017         uint256 nullifier = spend.nullifier;
1018         if (mapTxSaplingNullifiers.count(nullifier) <= 1) {
1019             continue;  // No conflict if zero or one spends
1020         }
1021         range_o = mapTxSaplingNullifiers.equal_range(nullifier);
1022         for (TxNullifiers::const_iterator it = range_o.first; it != range_o.second; ++it) {
1023             result.insert(it->second);
1024         }
1025     }
1026     return result;
1027 }
1028
1029 void CWallet::Flush(bool shutdown)
1030 {
1031     bitdb.Flush(shutdown);
1032 }
1033
1034 bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
1035 {
1036     if (!bitdb.Open(GetDataDir()))
1037     {
1038         // try moving the database env out of the way
1039         boost::filesystem::path pathDatabase = GetDataDir() / "database";
1040         boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%d.bak", GetTime());
1041         try {
1042             boost::filesystem::rename(pathDatabase, pathDatabaseBak);
1043             LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string());
1044         } catch (const boost::filesystem::filesystem_error&) {
1045             // failure is ok (well, not really, but it's not worse than what we started with)
1046         }
1047
1048         // try again
1049         if (!bitdb.Open(GetDataDir())) {
1050             // if it still fails, it probably means we can't even create the database env
1051             string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
1052             errorString += msg;
1053             return true;
1054         }
1055     }
1056
1057     if (GetBoolArg("-salvagewallet", false))
1058     {
1059         // Recover readable keypairs:
1060         if (!CWalletDB::Recover(bitdb, walletFile, true))
1061             return false;
1062     }
1063
1064     if (boost::filesystem::exists(GetDataDir() / walletFile))
1065     {
1066         CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
1067         if (r == CDBEnv::RECOVER_OK)
1068         {
1069             warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
1070                                      " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
1071                                      " your balance or transactions are incorrect you should"
1072                                      " restore from a backup."), GetDataDir());
1073         }
1074         if (r == CDBEnv::RECOVER_FAIL)
1075             errorString += _("wallet.dat corrupt, salvage failed");
1076     }
1077
1078     return true;
1079 }
1080
1081 template <class T>
1082 void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
1083 {
1084     // We want all the wallet transactions in range to have the same metadata as
1085     // the oldest (smallest nOrderPos).
1086     // So: find smallest nOrderPos:
1087
1088     int nMinOrderPos = std::numeric_limits<int>::max();
1089     const CWalletTx* copyFrom = NULL;
1090     for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
1091     {
1092         const uint256& hash = it->second;
1093         int n = mapWallet[hash].nOrderPos;
1094         if (n < nMinOrderPos)
1095         {
1096             nMinOrderPos = n;
1097             copyFrom = &mapWallet[hash];
1098         }
1099     }
1100     // Now copy data from copyFrom to rest:
1101     for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
1102     {
1103         const uint256& hash = it->second;
1104         CWalletTx* copyTo = &mapWallet[hash];
1105         if (copyFrom == copyTo) continue;
1106         copyTo->mapValue = copyFrom->mapValue;
1107         // mapSproutNoteData and mapSaplingNoteData not copied on purpose
1108         // (it is always set correctly for each CWalletTx)
1109         copyTo->vOrderForm = copyFrom->vOrderForm;
1110         // fTimeReceivedIsTxTime not copied on purpose
1111         // nTimeReceived not copied on purpose
1112         copyTo->nTimeSmart = copyFrom->nTimeSmart;
1113         copyTo->fFromMe = copyFrom->fFromMe;
1114         copyTo->strFromAccount = copyFrom->strFromAccount;
1115         // nOrderPos not copied on purpose
1116         // cached members not copied on purpose
1117     }
1118 }
1119
1120 /**
1121  * Outpoint is spent if any non-conflicted transaction
1122  * spends it:
1123  */
1124 bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
1125 {
1126     const COutPoint outpoint(hash, n);
1127     pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
1128     range = mapTxSpends.equal_range(outpoint);
1129
1130     for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
1131     {
1132         const uint256& wtxid = it->second;
1133         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
1134         if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
1135             return true; // Spent
1136     }
1137     return false;
1138 }
1139
1140 /**
1141  * Note is spent if any non-conflicted transaction
1142  * spends it:
1143  */
1144 bool CWallet::IsSproutSpent(const uint256& nullifier) const {
1145     pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
1146     range = mapTxSproutNullifiers.equal_range(nullifier);
1147
1148     for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
1149         const uint256& wtxid = it->second;
1150         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
1151         if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
1152             return true; // Spent
1153         }
1154     }
1155     return false;
1156 }
1157
1158 bool CWallet::IsSaplingSpent(const uint256& nullifier) const {
1159     pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
1160     range = mapTxSaplingNullifiers.equal_range(nullifier);
1161
1162     for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
1163         const uint256& wtxid = it->second;
1164         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
1165         if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
1166             return true; // Spent
1167         }
1168     }
1169     return false;
1170 }
1171
1172 void CWallet::AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid)
1173 {
1174     mapTxSpends.insert(make_pair(outpoint, wtxid));
1175
1176     pair<TxSpends::iterator, TxSpends::iterator> range;
1177     range = mapTxSpends.equal_range(outpoint);
1178     SyncMetaData<COutPoint>(range);
1179 }
1180
1181 void CWallet::AddToSproutSpends(const uint256& nullifier, const uint256& wtxid)
1182 {
1183     mapTxSproutNullifiers.insert(make_pair(nullifier, wtxid));
1184
1185     pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
1186     range = mapTxSproutNullifiers.equal_range(nullifier);
1187     SyncMetaData<uint256>(range);
1188 }
1189
1190 void CWallet::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid)
1191 {
1192     mapTxSaplingNullifiers.insert(make_pair(nullifier, wtxid));
1193
1194     pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
1195     range = mapTxSaplingNullifiers.equal_range(nullifier);
1196     SyncMetaData<uint256>(range);
1197 }
1198
1199 void CWallet::AddToSpends(const uint256& wtxid)
1200 {
1201     assert(mapWallet.count(wtxid));
1202     CWalletTx& thisTx = mapWallet[wtxid];
1203     if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
1204         return;
1205
1206     for (const CTxIn& txin : thisTx.vin) {
1207         AddToTransparentSpends(txin.prevout, wtxid);
1208     }
1209     for (const JSDescription& jsdesc : thisTx.vJoinSplit) {
1210         for (const uint256& nullifier : jsdesc.nullifiers) {
1211             AddToSproutSpends(nullifier, wtxid);
1212         }
1213     }
1214     for (const SpendDescription &spend : thisTx.vShieldedSpend) {
1215         AddToSaplingSpends(spend.nullifier, wtxid);
1216     }
1217 }
1218
1219 void CWallet::ClearNoteWitnessCache()
1220 {
1221     LOCK(cs_wallet);
1222     for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1223         for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) {
1224             item.second.witnesses.clear();
1225             item.second.witnessHeight = -1;
1226         }
1227         for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
1228             item.second.witnesses.clear();
1229             item.second.witnessHeight = -1;
1230         }
1231     }
1232     nWitnessCacheSize = 0;
1233     //fprintf(stderr,"Clear witness cache\n");
1234 }
1235
1236 template<typename NoteDataMap>
1237 void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
1238 {
1239     for (auto& item : noteDataMap) {
1240         auto* nd = &(item.second);
1241         // Only increment witnesses that are behind the current height
1242         if (nd->witnessHeight < indexHeight) {
1243             // Check the validity of the cache
1244             // The only time a note witnessed above the current height
1245             // would be invalid here is during a reindex when blocks
1246             // have been decremented, and we are incrementing the blocks
1247             // immediately after.
1248             assert(nWitnessCacheSize >= nd->witnesses.size());
1249             // Witnesses being incremented should always be either -1
1250             // (never incremented or decremented) or one below indexHeight
1251             assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight - 1));
1252             // Copy the witness for the previous block if we have one
1253             if (nd->witnesses.size() > 0) {
1254                 nd->witnesses.push_front(nd->witnesses.front());
1255             }
1256             if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
1257                 nd->witnesses.pop_back();
1258             }
1259         }
1260     }
1261 }
1262
1263 template<typename NoteDataMap>
1264 void AppendNoteCommitment(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment)
1265 {
1266     for (auto& item : noteDataMap) {
1267         auto* nd = &(item.second);
1268         if (nd->witnessHeight < indexHeight && nd->witnesses.size() > 0) {
1269             // Check the validity of the cache
1270             // See comment in CopyPreviousWitnesses about validity.
1271             assert(nWitnessCacheSize >= nd->witnesses.size());
1272             nd->witnesses.front().append(note_commitment);
1273         }
1274     }
1275 }
1276
1277 template<typename OutPoint, typename NoteData, typename Witness>
1278 void WitnessNoteIfMine(std::map<OutPoint, NoteData>& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const OutPoint& key, const Witness& witness)
1279 {
1280     if (noteDataMap.count(key) && noteDataMap[key].witnessHeight < indexHeight) {
1281         auto* nd = &(noteDataMap[key]);
1282         if (nd->witnesses.size() > 0) {
1283             // We think this can happen because we write out the
1284             // witness cache state after every block increment or
1285             // decrement, but the block index itself is written in
1286             // batches. So if the node crashes in between these two
1287             // operations, it is possible for IncrementNoteWitnesses
1288             // to be called again on previously-cached blocks. This
1289             // doesn't affect existing cached notes because of the
1290             // NoteData::witnessHeight checks. See #1378 for details.
1291             LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n",
1292                         key.ToString(), nd->witnesses.size(),
1293                         nd->witnessHeight,
1294                         nd->witnesses.front().root().GetHex(),
1295                         indexHeight,
1296                         witness.root().GetHex());
1297             nd->witnesses.clear();
1298         }
1299         nd->witnesses.push_front(witness);
1300         // Set height to one less than pindex so it gets incremented
1301         nd->witnessHeight = indexHeight - 1;
1302         // Check the validity of the cache
1303         assert(nWitnessCacheSize >= nd->witnesses.size());
1304     }
1305 }
1306
1307
1308 template<typename NoteDataMap>
1309 void UpdateWitnessHeights(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
1310 {
1311     for (auto& item : noteDataMap) {
1312         auto* nd = &(item.second);
1313         if (nd->witnessHeight < indexHeight) {
1314             nd->witnessHeight = indexHeight;
1315             // Check the validity of the cache
1316             // See comment in CopyPreviousWitnesses about validity.
1317             assert(nWitnessCacheSize >= nd->witnesses.size());
1318         }
1319     }
1320 }
1321
1322 void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
1323                                      const CBlock* pblockIn,
1324                                      SproutMerkleTree& sproutTree,
1325                                      SaplingMerkleTree& saplingTree)
1326 {
1327     LOCK(cs_wallet);
1328     for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1329        ::CopyPreviousWitnesses(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize);
1330        ::CopyPreviousWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize);
1331     }
1332
1333     if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
1334         nWitnessCacheSize += 1;
1335     }
1336
1337     const CBlock* pblock {pblockIn};
1338     CBlock block;
1339     if (!pblock) {
1340         ReadBlockFromDisk(block, pindex, Params().GetConsensus());
1341         pblock = &block;
1342     }
1343
1344     for (const CTransaction& tx : pblock->vtx) {
1345         auto hash = tx.GetHash();
1346         bool txIsOurs = mapWallet.count(hash);
1347         // Sprout
1348         for (size_t i = 0; i < tx.vJoinSplit.size(); i++) {
1349             const JSDescription& jsdesc = tx.vJoinSplit[i];
1350             for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) {
1351                 const uint256& note_commitment = jsdesc.commitments[j];
1352                 sproutTree.append(note_commitment);
1353
1354                 // Increment existing witnesses
1355                 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1356                     ::AppendNoteCommitment(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
1357                 }
1358
1359                 // If this is our note, witness it
1360                 if (txIsOurs) {
1361                     JSOutPoint jsoutpt {hash, i, j};
1362                     ::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, jsoutpt, sproutTree.witness());
1363                 }
1364             }
1365         }
1366         // Sapling
1367         for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) {
1368             const uint256& note_commitment = tx.vShieldedOutput[i].cm;
1369             saplingTree.append(note_commitment);
1370
1371             // Increment existing witnesses
1372             for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1373                 ::AppendNoteCommitment(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
1374             }
1375
1376             // If this is our note, witness it
1377             if (txIsOurs) {
1378                 SaplingOutPoint outPoint {hash, i};
1379                 ::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, outPoint, saplingTree.witness());
1380             }
1381         }
1382     }
1383
1384     // Update witness heights
1385     for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1386         ::UpdateWitnessHeights(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize);
1387         ::UpdateWitnessHeights(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize);
1388     }
1389
1390     // For performance reasons, we write out the witness cache in
1391     // CWallet::SetBestChain() (which also ensures that overall consistency
1392     // of the wallet.dat is maintained).
1393 }
1394
1395 template<typename NoteDataMap>
1396 bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
1397 {
1398     extern int32_t KOMODO_REWIND;
1399
1400     for (auto& item : noteDataMap) {
1401         auto* nd = &(item.second);
1402         // Only decrement witnesses that are not above the current height
1403         if (nd->witnessHeight <= indexHeight) {
1404             // Check the validity of the cache
1405             // See comment below (this would be invalid if there were a
1406             // prior decrement).
1407             assert(nWitnessCacheSize >= nd->witnesses.size());
1408             // Witnesses being decremented should always be either -1
1409             // (never incremented or decremented) or equal to the height
1410             // of the block being removed (indexHeight)
1411             if (!((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight)))
1412             {
1413                 printf("at height %d\n", indexHeight);
1414                 return false;
1415             }
1416             if (nd->witnesses.size() > 0) {
1417                 nd->witnesses.pop_front();
1418             }
1419             // indexHeight is the height of the block being removed, so 
1420             // the new witness cache height is one below it.
1421             nd->witnessHeight = indexHeight - 1;
1422         }
1423         // Check the validity of the cache
1424         // Technically if there are notes witnessed above the current
1425         // height, their cache will now be invalid (relative to the new
1426         // value of nWitnessCacheSize). However, this would only occur
1427         // during a reindex, and by the time the reindex reaches the tip
1428         // of the chain again, the existing witness caches will be valid
1429         // again.
1430         // We don't set nWitnessCacheSize to zero at the start of the
1431         // reindex because the on-disk blocks had already resulted in a
1432         // chain that didn't trigger the assertion below.
1433         if (nd->witnessHeight < indexHeight) {
1434             // Subtract 1 to compare to what nWitnessCacheSize will be after
1435             // decrementing.
1436             assert((nWitnessCacheSize - 1) >= nd->witnesses.size());
1437         }
1438     }
1439     assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0);
1440     return true;
1441 }
1442
1443 void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
1444 {
1445     LOCK(cs_wallet);
1446     for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1447         if (!::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize))
1448             needsRescan = true;
1449         if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize))
1450             needsRescan = true;
1451     }
1452     if (nWitnessCacheSize != 0)
1453     {
1454         nWitnessCacheSize -= 1;
1455         // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302)
1456         if (nWitnessCacheSize == 0)
1457         {
1458             ClearNoteWitnessCache();
1459         }
1460         //assert(nWitnessCacheSize > 0);
1461     }
1462
1463     // For performance reasons, we write out the witness cache in
1464     // CWallet::SetBestChain() (which also ensures that overall consistency
1465     // of the wallet.dat is maintained).
1466 }
1467
1468 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
1469 {
1470     if (IsCrypted())
1471         return false;
1472
1473     CKeyingMaterial vMasterKey;
1474
1475     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
1476     GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
1477
1478     CMasterKey kMasterKey;
1479
1480     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
1481     GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
1482
1483     CCrypter crypter;
1484     int64_t nStartTime = GetTimeMillis();
1485     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
1486     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
1487
1488     nStartTime = GetTimeMillis();
1489     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
1490     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
1491
1492     if (kMasterKey.nDeriveIterations < 25000)
1493         kMasterKey.nDeriveIterations = 25000;
1494
1495     LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
1496
1497     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
1498         return false;
1499     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
1500         return false;
1501
1502     {
1503         LOCK(cs_wallet);
1504         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
1505         if (fFileBacked)
1506         {
1507             assert(!pwalletdbEncryption);
1508             pwalletdbEncryption = new CWalletDB(strWalletFile);
1509             if (!pwalletdbEncryption->TxnBegin()) {
1510                 delete pwalletdbEncryption;
1511                 pwalletdbEncryption = NULL;
1512                 return false;
1513             }
1514             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
1515         }
1516
1517         if (!EncryptKeys(vMasterKey))
1518         {
1519             if (fFileBacked) {
1520                 pwalletdbEncryption->TxnAbort();
1521                 delete pwalletdbEncryption;
1522             }
1523             // We now probably have half of our keys encrypted in memory, and half not...
1524             // die and let the user reload the unencrypted wallet.
1525             assert(false);
1526         }
1527
1528         // Encryption was introduced in version 0.4.0
1529         SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
1530
1531         if (fFileBacked)
1532         {
1533             if (!pwalletdbEncryption->TxnCommit()) {
1534                 delete pwalletdbEncryption;
1535                 // We now have keys encrypted in memory, but not on disk...
1536                 // die to avoid confusion and let the user reload the unencrypted wallet.
1537                 assert(false);
1538             }
1539
1540             delete pwalletdbEncryption;
1541             pwalletdbEncryption = NULL;
1542         }
1543
1544         Lock();
1545         Unlock(strWalletPassphrase);
1546         NewKeyPool();
1547         Lock();
1548
1549         // Need to completely rewrite the wallet file; if we don't, bdb might keep
1550         // bits of the unencrypted private key in slack space in the database file.
1551         CDB::Rewrite(strWalletFile);
1552
1553     }
1554     NotifyStatusChanged(this);
1555
1556     return true;
1557 }
1558
1559 int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
1560 {
1561     AssertLockHeld(cs_wallet); // nOrderPosNext
1562     int64_t nRet = nOrderPosNext++;
1563     if (pwalletdb) {
1564         pwalletdb->WriteOrderPosNext(nOrderPosNext);
1565     } else {
1566         CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
1567     }
1568     return nRet;
1569 }
1570
1571 CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
1572 {
1573     AssertLockHeld(cs_wallet); // mapWallet
1574     CWalletDB walletdb(strWalletFile);
1575
1576     // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
1577     TxItems txOrdered;
1578
1579     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1580     // would make this much faster for applications that do this a lot.
1581     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1582     {
1583         CWalletTx* wtx = &((*it).second);
1584         txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
1585     }
1586     acentries.clear();
1587     walletdb.ListAccountCreditDebit(strAccount, acentries);
1588     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1589     {
1590         txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
1591     }
1592
1593     return txOrdered;
1594 }
1595
1596 // looks through all wallet UTXOs and checks to see if any qualify to stake the block at the current height. it always returns the qualified
1597 // UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving
1598 // each attempt consists of taking a VerusHash of the following values:
1599 //  ASSETCHAINS_MAGIC, nHeight, txid, voutNum
1600 bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const
1601 {
1602     arith_uint256 target;
1603     arith_uint256 curHash;
1604     COutput *pwinner = NULL;
1605     CWalletTx winnerWtx;
1606
1607     txnouttype whichType;
1608     std:vector<std::vector<unsigned char>> vSolutions;
1609
1610     pBlock->nNonce.SetPOSTarget(bnTarget, pBlock->nVersion);
1611     target.SetCompact(bnTarget);
1612
1613     auto consensusParams = Params().GetConsensus();
1614     CValidationState state;
1615
1616     std::vector<COutput> vecOutputs;
1617     std::vector<CWalletTx> vwtx;
1618     CAmount totalStakingAmount = 0;
1619
1620     uint32_t solutionVersion = CConstVerusSolutionVector::GetVersionByHeight(nHeight);
1621     bool extendedStake = solutionVersion >= CActivationHeight::ACTIVATE_EXTENDEDSTAKE;
1622
1623     {
1624         LOCK2(cs_main, cs_wallet);
1625         pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
1626
1627         int newSize = 0;
1628
1629         for (int i = 0; i < vecOutputs.size(); i++)
1630         {
1631             auto &txout = vecOutputs[i];
1632             COptCCParams p;
1633
1634             if (txout.tx &&
1635                 txout.i < txout.tx->vout.size() &&
1636                 txout.tx->vout[txout.i].nValue > 0 &&
1637                 txout.fSpendable &&
1638                 (txout.nDepth >= VERUS_MIN_STAKEAGE) &&
1639                 ((txout.tx->vout[txout.i].scriptPubKey.IsPayToCryptoCondition(p) &&
1640                   extendedStake && 
1641                   p.IsValid() && 
1642                   txout.tx->vout[txout.i].scriptPubKey.IsSpendableOutputType(p)) ||
1643                 (!p.IsValid() && 
1644                  Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) &&
1645                  (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH))))
1646             {
1647                 totalStakingAmount += txout.tx->vout[txout.i].nValue;
1648                 // if all are valid, no change, else compress
1649                 if (newSize != i)
1650                 {
1651                     vecOutputs[newSize] = txout;
1652                 }
1653                 newSize++;
1654             }
1655         }
1656
1657         if (newSize)
1658         {
1659             // no reallocations to move objects. do all at once, so we can release the wallet lock
1660             vecOutputs.resize(newSize);
1661             vwtx.resize(newSize);
1662             for (int i = 0; i < vecOutputs.size(); i++)
1663             {
1664                 vwtx[i] = *vecOutputs[i].tx;
1665                 vecOutputs[i].tx = &vwtx[i];
1666             }
1667         }
1668     }
1669
1670     if (totalStakingAmount)
1671     {
1672         LogPrintf("Staking with %s VRSC\n", ValueFromAmount(totalStakingAmount).write().c_str());
1673     }
1674     else
1675     {
1676         LogPrintf("No VRSC staking\n");
1677         return false;
1678     }
1679
1680     // we get these sources of entropy to prove all sources in the header
1681     int posHeight = -1, powHeight = -1, altHeight = -1;
1682     uint256 pastHash;
1683     {
1684         LOCK(cs_main);
1685         pastHash = chainActive.GetVerusEntropyHash(nHeight, &posHeight, &powHeight, &altHeight);
1686         if (extendedStake && (altHeight == -1 && (powHeight == -1 || posHeight == -1)))
1687         {
1688             printf("Error retrieving entropy hash at height %d, posHeight: %d, powHeight: %d, altHeight: %d\n", nHeight, posHeight, powHeight, altHeight);
1689             LogPrintf("Error retrieving entropy hash at height %d, posHeight: %d, powHeight: %d, altHeight: %d\n", nHeight, posHeight, powHeight, altHeight);
1690             return false;
1691         }
1692     }
1693
1694     // secondBlockHeight is either less than first or -1 if there isn't one
1695     int secondBlockHeight = altHeight != -1 ? 
1696                                 altHeight : 
1697                                 posHeight == -1 ? 
1698                                     posHeight :
1699                                     powHeight == -1 ?
1700                                         powHeight :
1701                                         (posHeight > powHeight ? 
1702                                             powHeight : 
1703                                             posHeight);
1704
1705     int proveBlockHeight = posHeight > secondBlockHeight ? posHeight : ((powHeight == -1) ? posHeight : powHeight);
1706
1707     if (proveBlockHeight == -1)
1708     {
1709         printf("No block suitable for proof for height %d, posHeight: %d, powHeight: %d, altHeight: %d\n", nHeight, posHeight, powHeight, altHeight);
1710         LogPrintf("No block suitable for proof for height %d, posHeight: %d, powHeight: %d, altHeight: %d\n", nHeight, posHeight, powHeight, altHeight);
1711     }
1712     else
1713     {
1714         CPOSNonce curNonce;
1715         uint32_t srcIndex;
1716
1717         CCoinsViewCache view(pcoinsTip);
1718         CMutableTransaction checkStakeTx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
1719         std::vector<CTxDestination> addressRet;
1720         int nRequiredRet;
1721
1722         BOOST_FOREACH(COutput &txout, vecOutputs)
1723         {
1724             COptCCParams p;
1725             std::vector<CTxDestination> destinations;
1726             int nRequired = 0;
1727             bool canSign = false, canSpend = false;
1728
1729             if (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target &&
1730                 ExtractDestinations(txout.tx->vout[txout.i].scriptPubKey, whichType, destinations, nRequired, this, &canSign, &canSpend) &&
1731                 ((txout.tx->vout[txout.i].scriptPubKey.IsPayToCryptoCondition(p) && 
1732                   extendedStake && 
1733                   canSpend) ||
1734                 (!p.IsValid() && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) && ::IsMine(*this, destinations[0]))))
1735             {
1736                 uint256 txHash = txout.tx->GetHash();
1737                 checkStakeTx.vin.push_back(CTxIn(COutPoint(txHash, txout.i)));
1738
1739                 LOCK2(cs_main, cs_wallet);
1740
1741                 if ((!pwinner || UintToArith256(curNonce) < UintToArith256(pBlock->nNonce)) &&
1742                     !cheatList.IsUTXOInList(COutPoint(txHash, txout.i), nHeight <= 100 ? 1 : nHeight-100))
1743                 {
1744                     if (view.HaveCoins(txHash) && Consensus::CheckTxInputs(checkStakeTx, state, view, nHeight, consensusParams))
1745                     {
1746                         //printf("Found PoS block\nnNonce:    %s\n", pBlock->nNonce.GetHex().c_str());
1747                         pwinner = &txout;
1748                         curNonce = pBlock->nNonce;
1749                         srcIndex = nHeight - txout.nDepth;
1750                     }
1751                     else
1752                     {
1753                         LogPrintf("Transaction %s failed to stake due to %s\n", txout.tx->GetHash().GetHex().c_str(), 
1754                                                                                 view.HaveCoins(txHash) ? "bad inputs" : "unavailable coins");
1755                     }
1756                 }
1757
1758                 checkStakeTx.vin.pop_back();
1759             }
1760         }
1761         if (pwinner)
1762         {
1763             stakeSource = static_cast<CTransaction>(*pwinner->tx);
1764
1765             // arith_uint256 post;
1766             // post.SetCompact(pBlock->GetVerusPOSTarget());
1767             // printf("Found stake transaction\n");
1768             // printf("POS hash: %s  \ntarget:   %s\n\n", 
1769             //         stakeSource.GetVerusPOSHash(&(pBlock->nNonce), pwinner->i, nHeight, pastHash).GetHex().c_str(), 
1770             //         ArithToUint256(post).GetHex().c_str());
1771
1772             voutNum = pwinner->i;
1773             pBlock->nNonce = curNonce;
1774
1775             if (solutionVersion >= CActivationHeight::ACTIVATE_STAKEHEADER)
1776             {
1777                 CDataStream headerStream = CDataStream(SER_NETWORK, PROTOCOL_VERSION);
1778
1779                 // store:
1780                 // 1. PBaaS header for this block
1781                 // 2. source transaction
1782                 // 3. block index of base MMR being used
1783                 // 4. source tx block index for proof
1784                 // 5. full merkle proof of source tx up to prior MMR root
1785                 // 6. block hash of block of entropyhash
1786                 // 7. proof of block hash (not full header) in the MMR for the block height of the entropy hash block
1787                 // all that data includes enough information to verify
1788                 // prior MMR, blockhash, transaction, entropy hash, and block indexes match
1789                 // also checks root match & block power
1790                 auto mmrView = chainActive.GetMMV();
1791                 pBlock->SetPrevMMRRoot(mmrView.GetRoot());
1792                 pBlock->AddUpdatePBaaSHeader();
1793
1794                 // get map and MMR for stake source transaction
1795                 CTransactionMap txMap(stakeSource);
1796                 TransactionMMView txView(txMap.transactionMMR);
1797                 uint256 txRoot = txView.GetRoot();
1798
1799                 std::vector<CTransactionComponentProof> txProofVec;
1800                 txProofVec.emplace_back(txView, txMap, stakeSource, CTransactionHeader::TX_HEADER, 0);
1801                 txProofVec.emplace_back(txView, txMap, stakeSource, CTransactionHeader::TX_OUTPUT, pwinner->i);
1802
1803                 // now, both the header and stake output are dependent on the transaction MMR root being provable up
1804                 // through the block MMR, and since we don't cache the new MMR proof for transactions yet, we need the block to create the proof.
1805                 // when we switch to the new MMR in place of a merkle tree, we can keep that in the wallet as well
1806                 CBlock block;
1807                 if (!ReadBlockFromDisk(block, chainActive[srcIndex], Params().GetConsensus(), false))
1808                 {
1809                     LogPrintf("%s: ERROR: could not read block number  %u from disk\n", __func__, srcIndex);
1810                     return false;
1811                 }
1812
1813                 BlockMMRange blockMMR(block.GetBlockMMRTree());
1814                 BlockMMView blockView(blockMMR);
1815
1816                 int txIndexPos;
1817                 for (txIndexPos = 0; txIndexPos < blockMMR.size(); txIndexPos++)
1818                 {
1819                     uint256 txRootHashFromMMR = blockMMR[txIndexPos].hash;
1820                     if (txRootHashFromMMR == txRoot)
1821                     {
1822                         //printf("tx with root %s found in block\n", txRootHashFromMMR.GetHex().c_str());
1823                         break;
1824                     }
1825                 }
1826
1827                 if (txIndexPos == blockMMR.size())
1828                 {
1829                     LogPrintf("%s: ERROR: could not find source transaction root in block %u\n", __func__, srcIndex);
1830                     return false;
1831                 }
1832
1833                 // prove the tx up to the MMR root, which also contains the block hash
1834                 CMMRProof txRootProof;
1835                 if (!blockView.GetProof(txRootProof, txIndexPos))
1836                 {
1837                     LogPrintf("%s: ERROR: could not create proof of source transaction in block %u\n", __func__, srcIndex);
1838                     return false;
1839                 }
1840
1841                 mmrView.resize(proveBlockHeight + 1);
1842                 chainActive.GetMerkleProof(mmrView, txRootProof, srcIndex);
1843
1844                 headerStream << CPartialTransactionProof(txRootProof, txProofVec);
1845
1846                 CMMRProof blockHeaderProof1;
1847                 if (!chainActive.GetBlockProof(mmrView, blockHeaderProof1, proveBlockHeight))
1848                 {
1849                     LogPrintf("%s: ERROR: could not create block proof for block %u\n", __func__, srcIndex);
1850                     return false;
1851                 }
1852                 headerStream << CBlockHeaderProof(blockHeaderProof1, chainActive[proveBlockHeight]->GetBlockHeader());
1853
1854                 CMMRProof blockHeaderProof2;
1855                 if (!chainActive.GetBlockProof(mmrView, blockHeaderProof2, secondBlockHeight))
1856                 {
1857                     LogPrintf("%s: ERROR: could not create block proof for second entropy source block %u\n", __func__, srcIndex);
1858                     chainActive.GetBlockProof(mmrView, blockHeaderProof2, secondBlockHeight); // repeat for debugging
1859                     return false;
1860                 }
1861                 headerStream << CBlockHeaderProof(blockHeaderProof2, chainActive[secondBlockHeight]->GetBlockHeader());
1862
1863                 std::vector<unsigned char> stx(headerStream.begin(), headerStream.end());
1864
1865                 // printf("\nFound Stake transaction... all proof serialized size == %lu\n", stx.size());
1866
1867                 CVerusSolutionVector(pBlock->nSolution).ResizeExtraData(stx.size());
1868
1869                 pBlock->SetExtraData(stx.data(), stx.size());
1870
1871                 //CBlockHeader blkHeader(*pBlock);
1872                 //CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
1873                 //printf("Staking block header size %ld\n", GetSerializeSize(s, blkHeader));
1874             }
1875             return true;
1876         }
1877     }
1878     return false;
1879 }
1880
1881 int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, std::vector<unsigned char> &utxosig, CTxDestination &rewardDest) const
1882 {
1883     CTransaction stakeSource;
1884     int32_t voutNum, siglen = 0;
1885     int64_t nValue;
1886     txnouttype whichType;
1887     std::vector<std::vector<unsigned char>> vSolutions;
1888
1889     CBlockIndex *tipindex = chainActive.LastTip();
1890     uint32_t stakeHeight = tipindex->GetHeight() + 1;
1891     bool extendedStake = CConstVerusSolutionVector::GetVersionByHeight(stakeHeight) >= CActivationHeight::ACTIVATE_EXTENDEDSTAKE;
1892
1893     bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
1894
1895     if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, stakeHeight, bnTarget))
1896     {
1897         //LogPrintf("Searched for eligible staking transactions, no winners found\n");
1898         return 0;
1899     }
1900
1901     bool signSuccess; 
1902     SignatureData sigdata; 
1903     uint64_t txfee;
1904     auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
1905
1906     const CKeyStore& keystore = *pwalletMain;
1907     txNew.vin.resize(1);
1908     txNew.vout.resize(1);
1909     txfee = 0;
1910     txNew.vin[0].prevout.hash = stakeSource.GetHash();
1911     txNew.vin[0].prevout.n = voutNum;
1912
1913     COptCCParams p;
1914     if (stakeSource.vout[voutNum].scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
1915     {
1916         if (!p.vKeys.size())
1917         {
1918             LogPrintf("%s: Please report - no destination on stake source\n");
1919             return 0;
1920         }
1921
1922         // send output to same destination as source, convert stakeguard into normal output, since
1923         // that is a spendable output that only works in coinbases. preserve all recipients and
1924         // min sigs
1925         if (p.evalCode == EVAL_STAKEGUARD)
1926         {
1927             // "CIdentity" is a dummy object type since an obj is not passed, and it does not make this an identity output
1928             txNew.vout[0].scriptPubKey = MakeMofNCCScript(CConditionObj<CIdentity>(0, p.vKeys, p.m));
1929         }
1930         else
1931         {
1932             txNew.vout[0].scriptPubKey = stakeSource.vout[voutNum].scriptPubKey;
1933         }
1934         rewardDest = p.vKeys[0];
1935     }
1936     else if (Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
1937     {
1938         if (whichType == TX_PUBKEY)
1939         {
1940             txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG;
1941             rewardDest = CPubKey(vSolutions[0]);
1942         }
1943         else if (whichType == TX_PUBKEYHASH)
1944         {
1945             txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
1946             rewardDest = CKeyID(uint160(vSolutions[0]));
1947         }
1948         else
1949         {
1950             LogPrintf("%s: Please report - found stake source that is not valid\n");
1951             return 0;
1952         }
1953     }
1954     else
1955     {
1956         return 0;
1957     }
1958
1959     // set expiry to time out after 100 blocks, so we can remove the transaction if it orphans
1960     txNew.nExpiryHeight = stakeHeight + 100;
1961
1962     uint256 srcBlock = uint256();
1963     CBlockIndex *pSrcIndex;
1964
1965     txNew.vout.push_back(CTxOut());
1966     CTxOut &txOut1 = txNew.vout[1];
1967     txOut1.nValue = 0;
1968     if (!GetTransaction(stakeSource.GetHash(), stakeSource, srcBlock))
1969         return 0;
1970     
1971     BlockMap::const_iterator it = mapBlockIndex.find(srcBlock);
1972     if (it == mapBlockIndex.end() || (pSrcIndex = it->second) == 0)
1973         return 0;
1974
1975     // !! DISABLE THIS FOR RELEASE: THIS MAKES A CHEAT TRANSACTION FOR EVERY STAKE FOR TESTING
1976     //CMutableTransaction cheat;
1977     //cheat = CMutableTransaction(txNew);
1978     //printf("TESTING ONLY: THIS SHOULD NOT BE ENABLED FOR RELEASE - MAKING CHEAT TRANSACTION FOR TESTING\n");
1979     //cheat.vout[1].scriptPubKey << OP_RETURN 
1980     //    << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, pSrcIndex->GetBlockHash(), pk).AsVector();
1981     // !! DOWN TO HERE
1982
1983     if (USE_EXTERNAL_PUBKEY)
1984     {
1985         rewardDest = CPubKey(ParseHex(NOTARY_PUBKEY));
1986     }
1987     else if (!VERUS_DEFAULTID.IsNull())
1988     {
1989         rewardDest = VERUS_DEFAULTID;
1990     }
1991
1992     if (rewardDest.which() == COptCCParams::ADDRTYPE_INVALID)
1993     {
1994         printf("%s: Invalid reward destinaton for stake\n", __func__);
1995         return 0;
1996     }
1997
1998     txOut1.scriptPubKey << OP_RETURN 
1999         << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, tipindex->GetBlockHash(), rewardDest).AsVector();
2000
2001     // !! DISABLE THIS FOR RELEASE: REMOVE THIS TOO
2002     //nValue = cheat.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
2003     //cheat.nLockTime = 0;
2004     //CTransaction cheatConst(cheat);
2005     //SignatureData cheatSig;
2006     //if (!ProduceSignature(TransactionSignatureCreator(&keystore, &cheatConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, cheatSig, consensusBranchId))
2007     //    fprintf(stderr,"failed to create cheat test signature\n");
2008     //else
2009     //{
2010     //    uint8_t *ptr;
2011     //    UpdateTransaction(cheat,0,cheatSig);
2012     //    cheatList.Add(CTxHolder(CTransaction(cheat), tipindex->GetHeight() + 1));
2013     //}
2014     // !! DOWN TO HERE
2015
2016     nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
2017
2018     txNew.nLockTime = 0;
2019     CTransaction txNewConst(txNew);
2020     signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, nValue, stakeSource.vout[voutNum].scriptPubKey), stakeSource.vout[voutNum].scriptPubKey, sigdata, consensusBranchId);
2021     if (!signSuccess)
2022     {
2023         fprintf(stderr,"failed to create signature\n");
2024         utxosig.clear();
2025     }
2026     else
2027     {
2028         uint8_t *ptr;
2029         UpdateTransaction(txNew, 0, sigdata);
2030         utxosig.resize(sigdata.scriptSig.size());
2031         memcpy(&(utxosig[0]), &(sigdata.scriptSig[0]), utxosig.size());
2032     }
2033     return(utxosig.size());
2034 }
2035
2036 void CWallet::MarkDirty()
2037 {
2038     {
2039         LOCK(cs_wallet);
2040         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
2041             item.second.MarkDirty();
2042     }
2043 }
2044
2045 /**
2046  * Ensure that every note in the wallet (for which we possess a spending key)
2047  * has a cached nullifier.
2048  */
2049 bool CWallet::UpdateNullifierNoteMap()
2050 {
2051     {
2052         LOCK(cs_wallet);
2053
2054         if (IsLocked())
2055             return false;
2056
2057         ZCNoteDecryption dec;
2058         for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
2059             for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) {
2060                 if (!item.second.nullifier) {
2061                     if (GetNoteDecryptor(item.second.address, dec)) {
2062                         auto i = item.first.js;
2063                         auto hSig = wtxItem.second.vJoinSplit[i].h_sig(
2064                             *pzcashParams, wtxItem.second.joinSplitPubKey);
2065                         item.second.nullifier = GetSproutNoteNullifier(
2066                             wtxItem.second.vJoinSplit[i],
2067                             item.second.address,
2068                             dec,
2069                             hSig,
2070                             item.first.n);
2071                     }
2072                 }
2073             }
2074
2075             // TODO: Sapling.  This method is only called from RPC walletpassphrase, which is currently unsupported
2076             // as RPC encryptwallet is hidden behind two flags: -developerencryptwallet -experimentalfeatures
2077
2078             UpdateNullifierNoteMapWithTx(wtxItem.second);
2079         }
2080     }
2081     return true;
2082 }
2083
2084 /**
2085  * Update mapSproutNullifiersToNotes and mapSaplingNullifiersToNotes
2086  * with the cached nullifiers in this tx.
2087  */
2088 void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
2089 {
2090     {
2091         LOCK(cs_wallet);
2092         for (const mapSproutNoteData_t::value_type& item : wtx.mapSproutNoteData) {
2093             if (item.second.nullifier) {
2094                 mapSproutNullifiersToNotes[*item.second.nullifier] = item.first;
2095             }
2096         }
2097
2098         for (const mapSaplingNoteData_t::value_type& item : wtx.mapSaplingNoteData) {
2099             if (item.second.nullifier) {
2100                 mapSaplingNullifiersToNotes[*item.second.nullifier] = item.first;
2101             }
2102         }
2103     }
2104 }
2105
2106 /**
2107  * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
2108  */
2109 void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
2110     LOCK(cs_wallet);
2111
2112     for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
2113         SaplingOutPoint op = item.first;
2114         SaplingNoteData nd = item.second;
2115
2116         if (nd.witnesses.empty()) {
2117             // If there are no witnesses, erase the nullifier and associated mapping.
2118             if (item.second.nullifier) {
2119                 mapSaplingNullifiersToNotes.erase(item.second.nullifier.get());
2120             }
2121             item.second.nullifier = boost::none;
2122         }
2123         else {
2124             uint64_t position = nd.witnesses.front().position();
2125             SaplingFullViewingKey fvk = mapSaplingFullViewingKeys.at(nd.ivk);
2126             OutputDescription output = wtx.vShieldedOutput[op.n];
2127             auto optPlaintext = SaplingNotePlaintext::decrypt(output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
2128             if (!optPlaintext) {
2129                 // An item in mapSaplingNoteData must have already been successfully decrypted,
2130                 // otherwise the item would not exist in the first place.
2131                 assert(false);
2132             }
2133             auto optNote = optPlaintext.get().note(nd.ivk);
2134             if (!optNote) {
2135                 assert(false);
2136             }
2137             auto optNullifier = optNote.get().nullifier(fvk, position);
2138             if (!optNullifier) {
2139                 // This should not happen.  If it does, maybe the position has been corrupted or miscalculated?
2140                 assert(false);
2141             }
2142             uint256 nullifier = optNullifier.get();
2143             mapSaplingNullifiersToNotes[nullifier] = op;
2144             item.second.nullifier = nullifier;
2145         }
2146     }
2147 }
2148
2149 /**
2150  * Iterate over transactions in a block and update the cached Sapling nullifiers
2151  * for transactions which belong to the wallet.
2152  */
2153 void CWallet::UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock) {
2154     LOCK(cs_wallet);
2155
2156     for (const CTransaction& tx : pblock->vtx) {
2157         auto hash = tx.GetHash();
2158         bool txIsOurs = mapWallet.count(hash);
2159         if (txIsOurs) {
2160             UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]);
2161         }
2162     }
2163 }
2164
2165 bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
2166 {
2167     uint256 hash = wtxIn.GetHash();
2168
2169     if (fFromLoadWallet)
2170     {
2171         mapWallet[hash] = wtxIn;
2172         mapWallet[hash].BindWallet(this);
2173         UpdateNullifierNoteMapWithTx(mapWallet[hash]);
2174         AddToSpends(hash);
2175     }
2176     else
2177     {
2178         LOCK(cs_wallet);
2179         // Inserts only if not already there, returns tx inserted or tx found
2180         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
2181         CWalletTx& wtx = (*ret.first).second;
2182         wtx.BindWallet(this);
2183         UpdateNullifierNoteMapWithTx(wtx);
2184         bool fInsertedNew = ret.second;
2185         if (fInsertedNew)
2186         {
2187             wtx.nTimeReceived = GetAdjustedTime();
2188             wtx.nOrderPos = IncOrderPosNext(pwalletdb);
2189
2190             wtx.nTimeSmart = wtx.nTimeReceived;
2191             if (!wtxIn.hashBlock.IsNull())
2192             {
2193                 if (mapBlockIndex.count(wtxIn.hashBlock))
2194                 {
2195                     int64_t latestNow = wtx.nTimeReceived;
2196                     int64_t latestEntry = 0;
2197                     {
2198                         // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2199                         int64_t latestTolerated = latestNow + 300;
2200                         std::list<CAccountingEntry> acentries;
2201                         TxItems txOrdered = OrderedTxItems(acentries);
2202                         for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
2203                         {
2204                             CWalletTx *const pwtx = (*it).second.first;
2205                             if (pwtx == &wtx)
2206                                 continue;
2207                             CAccountingEntry *const pacentry = (*it).second.second;
2208                             int64_t nSmartTime;
2209                             if (pwtx)
2210                             {
2211                                 nSmartTime = pwtx->nTimeSmart;
2212                                 if (!nSmartTime)
2213                                     nSmartTime = pwtx->nTimeReceived;
2214                             }
2215                             else
2216                                 nSmartTime = pacentry->nTime;
2217                             if (nSmartTime <= latestTolerated)
2218                             {
2219                                 latestEntry = nSmartTime;
2220                                 if (nSmartTime > latestNow)
2221                                     latestNow = nSmartTime;
2222                                 break;
2223                             }
2224                         }
2225                     }
2226
2227                     int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
2228                     wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2229                 }
2230                 else
2231                     LogPrintf("AddToWallet(): found %s in block %s not in index\n",
2232                              wtxIn.GetHash().ToString(),
2233                              wtxIn.hashBlock.ToString());
2234             }
2235             AddToSpends(hash);
2236         }
2237
2238         bool fUpdated = false;
2239         if (!fInsertedNew)
2240         {
2241             // Merge
2242             if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
2243             {
2244                 wtx.hashBlock = wtxIn.hashBlock;
2245                 fUpdated = true;
2246             }
2247             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
2248             {
2249                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
2250                 wtx.nIndex = wtxIn.nIndex;
2251                 fUpdated = true;
2252             }
2253             if (UpdatedNoteData(wtxIn, wtx)) {
2254                 fUpdated = true;
2255             }
2256             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
2257             {
2258                 wtx.fFromMe = wtxIn.fFromMe;
2259                 fUpdated = true;
2260             }
2261         }
2262
2263         //// debug log out
2264         if (fDebug)
2265         {
2266             LogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
2267         }
2268
2269         // Write to disk
2270         if (fInsertedNew || fUpdated)
2271             if (!wtx.WriteToDisk(pwalletdb))
2272                 return false;
2273
2274         // Break debit/credit balance caches:
2275         wtx.MarkDirty();
2276
2277         // Notify UI of new or updated transaction
2278         NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
2279
2280         // notify an external script when a wallet transaction comes in or is updated
2281         std::string strCmd = GetArg("-walletnotify", "");
2282
2283         if ( !strCmd.empty())
2284         {
2285             boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
2286             boost::thread t(runCommand, strCmd); // thread runs free
2287         }
2288
2289     }
2290     return true;
2291 }
2292
2293 bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
2294 {
2295     bool unchangedSproutFlag = (wtxIn.mapSproutNoteData.empty() || wtxIn.mapSproutNoteData == wtx.mapSproutNoteData);
2296     if (!unchangedSproutFlag) {
2297         auto tmp = wtxIn.mapSproutNoteData;
2298         // Ensure we keep any cached witnesses we may already have
2299         for (const std::pair <JSOutPoint, SproutNoteData> nd : wtx.mapSproutNoteData) {
2300             if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
2301                 tmp.at(nd.first).witnesses.assign(
2302                         nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
2303             }
2304             tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
2305         }
2306         // Now copy over the updated note data
2307         wtx.mapSproutNoteData = tmp;
2308     }
2309
2310     bool unchangedSaplingFlag = (wtxIn.mapSaplingNoteData.empty() || wtxIn.mapSaplingNoteData == wtx.mapSaplingNoteData);
2311     if (!unchangedSaplingFlag) {
2312         auto tmp = wtxIn.mapSaplingNoteData;
2313         // Ensure we keep any cached witnesses we may already have
2314
2315         for (const std::pair <SaplingOutPoint, SaplingNoteData> nd : wtx.mapSaplingNoteData) {
2316             if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
2317                 tmp.at(nd.first).witnesses.assign(
2318                         nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
2319             }
2320             tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
2321         }
2322
2323         // Now copy over the updated note data
2324         wtx.mapSaplingNoteData = tmp;
2325     }
2326
2327     return !unchangedSproutFlag || !unchangedSaplingFlag;
2328 }
2329
2330 std::pair<bool, bool> CWallet::CheckAuthority(const CIdentity &identity)
2331 {
2332     std::pair<bool, bool> canSignCanSpend({false, false});
2333     if (!identity.IsValidUnrevoked())
2334     {
2335         return canSignCanSpend;
2336     }
2337     std::set<CIdentityID> keySet;
2338
2339     // determine our status of cansign or canspend for this new ID
2340     for (auto key : identity.primaryAddresses)
2341     {
2342         CKeyID keyID = CKeyID(GetDestinationID(key));
2343         if (HaveKey(keyID))
2344         {
2345             keySet.insert(keyID);
2346         }
2347     }
2348
2349     // if we have enough keys to fully authorize, it is ours
2350     if (keySet.size() >= identity.minSigs)
2351     {
2352         canSignCanSpend.first = true;
2353         canSignCanSpend.second = true;
2354     }
2355     else if (keySet.size())
2356     {
2357         canSignCanSpend.first = true;
2358     }
2359     return canSignCanSpend;
2360 }
2361
2362 bool CWallet::MarkIdentityDirty(const CIdentityID &idID)
2363 {
2364     bool found = false;
2365     // if we already had signing authority, but not spending, enumerate wallet transactions sent to this ID and mark them dirty
2366     // for proper balance calculation
2367     for (auto &txidAndWtx : mapWallet)
2368     {
2369         bool dirty = false;
2370         txnouttype txType;
2371         std::vector<CTxDestination> addresses;
2372         int minSigs;
2373         for (auto txout : txidAndWtx.second.vout)
2374         {
2375             if (txout.scriptPubKey.IsPayToCryptoCondition() && ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs))
2376             {
2377                 for (auto dest : addresses)
2378                 {
2379                     if (GetDestinationID(dest) == idID)
2380                     {
2381                         dirty = true;
2382                         found = true;
2383                         break;
2384                     }
2385                 }
2386             }
2387         }
2388         if (dirty)
2389         {
2390             txidAndWtx.second.MarkDirty();
2391         }
2392     }
2393     return found;
2394 }
2395
2396 /**
2397  * Add a transaction to the wallet, or update it.
2398  * pblock is optional, but should be provided if the transaction is known to be in a block.
2399  * If fUpdate is true, existing transactions will be updated.
2400  *
2401  * If pblock is null, this transaction has either recently entered the mempool from the
2402  * network, is re-entering the mempool after a block was disconnected, or is exiting the
2403  * mempool because it conflicts with another transaction. In all these cases, if there is
2404  * an existing wallet transaction, the wallet transaction's Merkle branch data is _not_
2405  * updated; instead, the transaction being in the mempool or conflicted is determined on
2406  * the fly in CMerkleTx::GetDepthInMainChain().
2407  */
2408 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
2409 {
2410     {
2411         AssertLockHeld(cs_wallet);
2412         AssertLockHeld(cs_main);
2413         uint256 txHash = tx.GetHash();
2414
2415         bool fExisted = mapWallet.count(txHash) != 0;
2416         if (fExisted && !fUpdate) return false;
2417         auto sproutNoteData = FindMySproutNotes(tx);
2418         auto saplingNoteDataAndAddressesToAdd = FindMySaplingNotes(tx);
2419         auto saplingNoteData = saplingNoteDataAndAddressesToAdd.first;
2420         auto addressesToAdd = saplingNoteDataAndAddressesToAdd.second;
2421         for (const auto &addressToAdd : addressesToAdd) {
2422             if (!AddSaplingIncomingViewingKey(addressToAdd.second, addressToAdd.first)) {
2423                 return false;
2424             }
2425         }
2426
2427         uint32_t nHeight = 0;
2428         if (pblock)
2429         {
2430             auto blkIndexIt = mapBlockIndex.find(pblock->GetHash());
2431             if (blkIndexIt != mapBlockIndex.end())
2432             {
2433                 nHeight = blkIndexIt->second->GetHeight();
2434             }
2435             else
2436             {
2437                 // this should never happen
2438                 assert(false);
2439             }
2440         }
2441
2442         for (auto output : tx.vout)
2443         {
2444             bool canSpend = false;
2445             COptCCParams p;
2446
2447             if (output.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.version >= p.VERSION_V3)
2448             {
2449                 CIdentityMapValue identity;
2450
2451                 if (p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size() && (*(CIdentity *)&identity = CIdentity(p.vData[0])).IsValid())
2452                 {
2453                     identity.txid = txHash;
2454                     CIdentityMapKey idMapKey = CIdentityMapKey(identity.GetID(), 
2455                                                                nHeight, 
2456                                                                1, 
2457                                                                CIdentityMapKey::VALID);
2458
2459                     std::set<CKeyID> keySet;
2460                     CIdentityID idID(identity.GetID());
2461                     int blockOrder = 1;
2462                     bool doneWithID = false;
2463
2464                     std::pair<CIdentityMapKey, CIdentityMapValue> idHistory;
2465
2466                     // if adding, current is what it will be, idHistory is what it was
2467                     // if we are deleting, current identity is what it was, idHistory is what it will be
2468                     std::pair<bool, bool> wasCanSignCanSpend({false, false});
2469                     std::pair<bool, bool> canSignCanSpend(CheckAuthority(identity));
2470
2471                     // if the new identity is revoked, the recovery identity holds can sign/can spend authority
2472                     if (identity.IsRevoked())
2473                     {
2474                         // if it's revoked, default is no authority for primary addresses, but we will have authority if
2475                         // we have control over the recovery identity
2476                         std::pair<CIdentityMapKey, CIdentityMapValue> recoveryAuthority;
2477                         if (GetIdentity(identity.recoveryAuthority, recoveryAuthority, nHeight ? nHeight : INT_MAX))
2478                         {
2479                             canSignCanSpend = CheckAuthority(recoveryAuthority.second);
2480                         }
2481                     }
2482
2483                     // does identity already exist in this wallet?
2484                     if (GetIdentity(idID, idHistory, nHeight ? nHeight : INT_MAX))
2485                     {
2486                         wasCanSignCanSpend = CheckAuthority(idHistory.second);
2487
2488                         if (idHistory.second.IsRevoked())
2489                         {
2490                             std::pair<CIdentityMapKey, CIdentityMapValue> oldRecoveryAuthority;
2491                             std::pair<bool, bool> auxCSCS;
2492                             // if we hold the recovery authority in our wallet, then set wasCanSignCanSpend pair to true
2493                             if (GetIdentity(idHistory.second.recoveryAuthority, 
2494                                             oldRecoveryAuthority, 
2495                                             nHeight ? nHeight : INT_MAX))
2496                             {
2497                                 auxCSCS = CheckAuthority(oldRecoveryAuthority.second);
2498                                 wasCanSignCanSpend = std::pair<bool, bool>({wasCanSignCanSpend.first || auxCSCS.first,
2499                                                                             wasCanSignCanSpend.second || auxCSCS.second});
2500                             }
2501                         }
2502
2503                         // if this is an add of the initial registration, delete all other instances of the ID
2504                         if (CNameReservation(tx).IsValid())
2505                         {
2506                             while (GetIdentity(idID, idHistory))
2507                             {
2508                                 // any definition of this identity in this wallet must be
2509                                 // invalid now
2510                                 RemoveIdentity(idHistory.first, idHistory.second.txid);
2511                                 if (idHistory.second.txid != txHash)
2512                                 {
2513                                     // any definition of this ID in this wallet that is not this definition
2514                                     // must also be on an invalid transaction
2515                                     EraseFromWallet(idHistory.second.txid);
2516                                 }
2517                                 // set wasCanSignCanSpend to true, true to delete any dependent transactions
2518                                 wasCanSignCanSpend = {true, true};
2519                             }
2520                             idHistory = std::pair<CIdentityMapKey, CIdentityMapValue>();
2521                             wasCanSignCanSpend = std::pair<bool, bool>({false, false});
2522                         }
2523                         else if (nHeight && idHistory.first.blockHeight == nHeight && idHistory.second.txid != identity.txid)
2524                         {
2525                             // this is one of more than one identity records in the same block
2526                             std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> thisHeightIdentities;
2527                             CIdentityMapKey heightKey(idID, nHeight);
2528                             GetIdentity(heightKey, heightKey, thisHeightIdentities);
2529
2530                             std::map<uint256, std::pair<CIdentityMapKey, CIdentityMapValue>> firstIDMap;
2531                             for (auto &foundID : thisHeightIdentities)
2532                             {
2533                                 firstIDMap[foundID.second.txid] = foundID;
2534                             }
2535
2536                             if (firstIDMap.count(identity.txid))
2537                             {
2538                                 doneWithID = true;
2539                             }
2540                             else
2541                             {
2542                                 blockOrder = thisHeightIdentities.size() + 1;
2543                                 firstIDMap.insert(make_pair(identity.txid, 
2544                                                             make_pair(CIdentityMapKey(idID, 
2545                                                                                         nHeight,
2546                                                                                         blockOrder, 
2547                                                                                         (canSignCanSpend.first ? CIdentityMapKey::CAN_SIGN : 0) + canSignCanSpend.second ? CIdentityMapKey::CAN_SPEND : 0), 
2548                                                                       identity)));
2549
2550                                 // now we have all the entries of the specified height, including those from before and the new one in the firstIDMap
2551                                 // the #1 in the block is one that has none of its input txes in the map. the last is not present in any input tx
2552                                 // to sort, we make a new map, indexed by the one that it spends, then follow the chain
2553                                 std::map<uint256, std::pair<CIdentityMapKey, CIdentityMapValue>> indexedByPrior;
2554                                 std::pair<CIdentityMapKey, CIdentityMapValue> firstInBlock;
2555
2556                                 for (auto &idEntry : firstIDMap)
2557                                 {
2558                                     uint256 spendsTxId;
2559                                     CTransaction entryTx;
2560                                     uint256 blkHash;
2561                                     if (!myGetTransaction(idEntry.first, entryTx, blkHash))
2562                                     {
2563                                         LogPrint("%s - error: cannot retrieve transaction %s during sort of identity transactions in block, blockchain state may be corrupt and need resynchronization\n", __func__, idEntry.first.GetHex().c_str());
2564                                     }
2565                                     else
2566                                     {
2567                                         bool isFirst = true;
2568                                         for (auto &input : entryTx.vin)
2569                                         {
2570                                             auto idMapIt = firstIDMap.find(input.prevout.hash);
2571                                             if (idMapIt != firstIDMap.end())
2572                                             {
2573                                                 indexedByPrior[input.prevout.hash] = idEntry.second;
2574                                                 isFirst = false;
2575                                             }
2576                                         }
2577                                         if (isFirst)
2578                                         {
2579                                             // this should first be added solo, so #1 should always be set
2580                                             if (idEntry.second.first.blockOrder != 1)
2581                                             {
2582                                                 LogPrint("%s - error: unexpected block order in %s\n", __func__, idEntry.first.GetHex().c_str());
2583                                             }
2584                                             firstInBlock = idEntry.second;
2585                                         }
2586                                     }
2587                                 }
2588
2589                                 if (!firstInBlock.first.IsValid())
2590                                 {
2591                                     LogPrint("%s - error: missing first in block\n", __func__);
2592                                 }
2593                                 else
2594                                 {
2595                                     // now validate that from 1st to last, we have order correct
2596                                     std::pair<CIdentityMapKey, CIdentityMapValue> *pCurID;
2597                                     int i = 1;
2598                                     for (pCurID = &firstInBlock; pCurID; i++)
2599                                     {
2600                                         if (pCurID->first.blockOrder != i)
2601                                         {
2602                                             LogPrint("%s - error: incorrect block order in entry %s\n", __func__, pCurID->second.txid.GetHex().c_str());
2603                                             printf("%s - error: incorrect block order in entry %s\n", __func__, pCurID->second.txid.GetHex().c_str());
2604                                         }
2605                                     }
2606                                 }
2607                             }
2608                         }
2609                         else if (nHeight && idHistory.first.blockHeight == nHeight)
2610                         {
2611                             // nHeight means this is an add, it has the same txid as an ID already present in the wallet, so we can ignore
2612                             doneWithID = true;
2613                         }
2614                         else
2615                         {
2616                             if (idHistory.first.flags & idHistory.first.CAN_SPEND)
2617                             {
2618                                 wasCanSignCanSpend.first = true;
2619                                 wasCanSignCanSpend.second = true;
2620                             }
2621                             else if ((idHistory.first.flags & idHistory.first.CAN_SIGN))
2622                             {
2623                                 wasCanSignCanSpend.first = true;
2624                             }
2625                             // if we are supposed to remove the last entry, do so
2626                             if (!pblock && txHash == idHistory.second.txid)
2627                             {
2628                                 RemoveIdentity(idHistory.first, idHistory.second.txid);
2629                             }
2630                         }
2631                     }
2632                     else if (!pblock)
2633                     {
2634                         // not present, nothing to delete
2635                         doneWithID = true;
2636                     }
2637
2638                     if (!doneWithID)
2639                     {
2640                         if (pblock)
2641                         {
2642                             // if we used to be able to sign with this identity, can now, or we put it on a manual hold, and it's not invalid or blacklisted, store it
2643                             if ((wasCanSignCanSpend.first || canSignCanSpend.first || (idHistory.first.flags & idHistory.first.MANUAL_HOLD)) && !(idHistory.first.flags & idHistory.first.BLACKLIST))
2644                             {
2645                                 idMapKey = CIdentityMapKey(identity.GetID(), 
2646                                                             nHeight, 
2647                                                             blockOrder, 
2648                                                             idHistory.first.VALID | 
2649                                                                 ((idHistory.second.IsValid() ? idHistory.first.flags : 0) & idHistory.first.MANUAL_HOLD) | 
2650                                                                 (canSignCanSpend.first ? idHistory.first.CAN_SIGN : 0) | 
2651                                                                 (canSignCanSpend.second ? idHistory.first.CAN_SPEND : 0));
2652                                 AddUpdateIdentity(idMapKey, identity);
2653                             }
2654                         }
2655                         else
2656                         {
2657                             std::pair<bool, bool> swapBools = canSignCanSpend;
2658                             canSignCanSpend = wasCanSignCanSpend;
2659                             wasCanSignCanSpend = swapBools;
2660                         }
2661
2662                         // store transitions as needed in the wallet
2663                         if (canSignCanSpend.first != wasCanSignCanSpend.first || canSignCanSpend.second != wasCanSignCanSpend.second)
2664                         {
2665                             // mark all transactions dirty to recalculate numbers
2666                             for (auto &txidAndWtx : mapWallet)
2667                             {
2668                                 // mark the whole wallet dirty. if this is an issue, we can optimize.
2669                                 txidAndWtx.second.MarkDirty();
2670                             }
2671
2672                             if (canSignCanSpend.first != wasCanSignCanSpend.first)
2673                             {
2674                                 if (canSignCanSpend.first)
2675                                 {
2676                                     // add all UTXOs sent to this ID to this wallet
2677                                     // and also check any other outputs that are sent to this ID to see if they have
2678                                     // been spent, and if so, add them as spends as well
2679                                     std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
2680                                     std::set<uint256> unspentTxSet;
2681                                     GetAddressUnspent(idID, CScript::P2ID, unspentOutputs);
2682
2683                                     // first, put all the txids of the UTXOs in a set to check intersection with wallet txes
2684                                     // that may already include outputs to the newly controlled ID. we also need to check wallet
2685                                     // txes that are not UTXOs to record spends, rather than considering them UTXOs
2686                                     for (auto &newOut : unspentOutputs)
2687                                     {
2688                                         unspentTxSet.insert(newOut.first.txhash);
2689                                     }
2690
2691                                     // now, look through existing wallet txes for outputs to the ID, which we did not, but now will
2692                                     // consider as ours and add them to the outputs that need to be checked
2693                                     for (auto &wtx : mapWallet)
2694                                     {
2695                                         // if it's not in the chain, or already in the unspent set to check, we don't need to add it to
2696                                         // anything
2697                                         if (!wtx.second.IsInMainChain() ||
2698                                             unspentTxSet.count(wtx.first))
2699                                         {
2700                                             continue;
2701                                         }
2702                                         int unspentOutputsSize = unspentOutputs.size();
2703                                         for (int k = 0; k < wtx.second.vout.size(); k++)
2704                                         {
2705                                             const CTxOut &oneOut = wtx.second.vout[k];
2706                                             txnouttype newTypeRet;
2707                                             std::vector<CTxDestination> newAddressRet;
2708                                             int newNRequired;
2709                                             bool newCanSign, newCanSpend;
2710                                             // if we think this output isn't spent and we couldn't sign for it, but the ID enables us to, 
2711                                             // then we need to check it further to see if we need to add other spending txes now
2712                                             if (IsSpent(wtx.first, k) ||
2713                                                 (ExtractDestinations(oneOut.scriptPubKey, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight) && newCanSign))
2714                                             {
2715                                                 continue;
2716                                             }
2717                                             for (auto &oneDest : newAddressRet)
2718                                             {
2719                                                 if (oneDest.which() == COptCCParams::ADDRTYPE_ID && GetDestinationID(oneDest) == idID)
2720                                                 {
2721                                                     CAddressUnspentKey unspentKey(CScript::P2ID, idID, wtx.first, k);
2722                                                     CBlockIndex *pIndex = mapBlockIndex[wtx.second.hashBlock];
2723                                                     unspentOutputs.push_back(
2724                                                         make_pair(unspentKey, CAddressUnspentValue(oneOut.nValue, oneOut.scriptPubKey, pIndex->GetHeight())));
2725                                                     // if we add one on a tx, no need to check more here
2726                                                     break;
2727                                                 }
2728                                             }
2729                                             // we only need to add one output to check all outputs below
2730                                             if (unspentOutputsSize < unspentOutputs.size())
2731                                             {
2732                                                 break;
2733                                             }
2734                                         }
2735                                         if (unspentOutputsSize < unspentOutputs.size())
2736                                         {
2737                                             continue;
2738                                         }
2739                                     }
2740
2741                                     auto consensus = Params().GetConsensus();
2742                                     for (auto &newOut : unspentOutputs)
2743                                     {
2744                                         // Do not flush the wallet here for performance reasons
2745                                         // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
2746                                         CWalletDB walletdb(strWalletFile, "r+", false);
2747
2748                                         txnouttype newTypeRet;
2749                                         std::vector<CTxDestination> newAddressRet;
2750                                         int newNRequired;
2751                                         bool newCanSign, newCanSpend;
2752                                         const CWalletTx *pWtx = GetWalletTx(newOut.first.txhash);
2753
2754                                         // check if already present and if its a CC output, so we know it can be sent to an identity
2755                                         if (pWtx == nullptr && newOut.second.script.IsPayToCryptoCondition())
2756                                         {
2757                                             CWalletTx wtx;
2758                                             if (!(ExtractDestinations(newOut.second.script, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
2759                                             {
2760                                                 continue;
2761                                             }
2762                                             uint256 blkHash;
2763                                             CTransaction newTx;
2764                                             if (myGetTransaction(newOut.first.txhash, newTx, blkHash))
2765                                             {
2766                                                 wtx = CWalletTx(this, newTx);
2767
2768                                                 // Get merkle branch if transaction was found in a block
2769                                                 CBlock block;
2770                                                 auto blkIndexIt = mapBlockIndex.find(blkHash);
2771                                                 if (!blkHash.IsNull() && blkIndexIt != mapBlockIndex.end() && chainActive.Contains(blkIndexIt->second))
2772                                                 {
2773                                                     // if it's supposed to be in a block, but can't be loaded, don't add without merkle
2774                                                     if (!ReadBlockFromDisk(block, blkIndexIt->second, consensus))
2775                                                     {
2776                                                         continue;
2777                                                     }
2778                                                     wtx.SetMerkleBranch(block);
2779                                                 }
2780
2781                                                 AddToWallet(wtx, false, &walletdb);
2782                                                 pWtx = GetWalletTx(newOut.first.txhash);
2783                                             }
2784                                         }
2785                                         else if (pWtx = GetWalletTx(newOut.first.txhash))
2786                                         {
2787                                             if (!(ExtractDestinations(newOut.second.script, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
2788                                             {
2789                                                 continue;
2790                                             }
2791                                         }
2792
2793                                         // if we were or are now in the wallet, we need to see if we should record new spends
2794                                         if (pWtx != nullptr && newOut.second.script.IsPayToCryptoCondition())
2795                                         {
2796                                             // while we know there is an unspent index to this ID on the new transaction output, we don't know
2797                                             // if there are other outputs to this ID on the transaction, which are already spent. 
2798                                             // if so, we need to record the spends in the wallet as well, or it will add them but
2799                                             // not consider them spent.
2800                                             uint256 spendBlkHash;
2801                                             CTransaction spendTx;
2802                                             std::vector<CTxOut> checkIfSpent = pWtx->vout;
2803                                             for (int i = 0; i < checkIfSpent.size(); i++)
2804                                             {
2805                                                 // if it really came from the unspent index and is the same output, don't bother looking for a spend
2806                                                 if (unspentTxSet.count(newOut.first.txhash) && newOut.first.index == i)
2807                                                 {
2808                                                     continue;
2809                                                 }
2810
2811                                                 // if we can't spend it, no need to check for spends
2812                                                 if (!(ExtractDestinations(checkIfSpent[i].scriptPubKey, 
2813                                                                           newTypeRet, 
2814                                                                           newAddressRet, 
2815                                                                           newNRequired, 
2816                                                                           this, 
2817                                                                           &newCanSign, 
2818                                                                           &newCanSpend,
2819                                                                           nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
2820                                                 {
2821                                                     continue;
2822                                                 }
2823
2824                                                 CSpentIndexValue spentInfo;
2825                                                 CSpentIndexKey spentKey(newOut.first.txhash, i);
2826                                                 if (GetSpentIndex(spentKey, spentInfo))
2827                                                 {
2828                                                     if (GetWalletTx(spentInfo.txid) == nullptr &&
2829                                                         spentInfo.blockHeight <= nHeight &&
2830                                                         myGetTransaction(spentInfo.txid, spendTx, spendBlkHash) && !spendBlkHash.IsNull())
2831                                                     {
2832                                                         CWalletTx spendWtx(this, spendTx);
2833
2834                                                         // Get merkle branch if transaction was found in a block
2835                                                         CBlock spendBlock;
2836                                                         auto spendBlkIndexIt = mapBlockIndex.find(spendBlkHash);
2837                                                         if (spendBlkIndexIt != mapBlockIndex.end() && 
2838                                                             chainActive.Contains(spendBlkIndexIt->second) &&
2839                                                             ReadBlockFromDisk(spendBlock, spendBlkIndexIt->second, consensus))
2840                                                         {
2841                                                             spendWtx.SetMerkleBranch(spendBlock);
2842                                                             AddToWallet(spendWtx, false, &walletdb);
2843
2844                                                             // add these outputs to the outputs we need to check if spent
2845                                                             // as long as we are adding spending transactions that are earlier
2846                                                             // or up to this height, we follow the spends
2847                                                             checkIfSpent.insert(checkIfSpent.end(), spendTx.vout.begin(), spendTx.vout.end());
2848                                                         }
2849                                                     }
2850                                                 }
2851                                             }
2852                                         }
2853                                     }
2854                                 }
2855                                 else
2856                                 {
2857                                     // we have gone from canSign to no control over this ID, either by deletion of tx or removal from signers. this will take effect retroactively on deletion and next block on addition
2858                                     // 1. remove all transactions that have UTXOs sent to this ID and are no longer can sign or can spend for us from the wallet
2859                                     // 2. if deletion, remove all transactions since the last idHistory that are in the wallet due to this ID
2860                                     // 3. remove all IDs from the wallet that are found in those removed transactions, are neither canSpend nor canSign, and are neither on manual hold nor present on any remaining transactions
2861                                     // 4. remove any transactions that are only in the wallet because they spend an output that was sent to this ID
2862
2863                                     std::set<CIdentityID> idsToCheck = std::set<CIdentityID>();
2864
2865                                     if (!pblock)
2866                                     {
2867                                         idsToCheck.insert(idID);
2868                                     }
2869
2870                                     // first and last blocks to consider when deleting spent transactions from the wallet
2871                                     uint32_t deleteSpentFrom;
2872                                     
2873                                     if (!pblock)
2874                                     {
2875                                         deleteSpentFrom = idHistory.first.blockHeight + 1;
2876                                     }
2877                                     else
2878                                     {
2879                                         deleteSpentFrom = idMapKey.blockHeight + 1;
2880                                     }
2881
2882                                     std::map<const uint256 *, CWalletTx *> txesToErase;
2883
2884                                     for (auto &txidAndWtx : mapWallet)
2885                                     {
2886                                         const CBlockIndex *pIndex;
2887                                         if (txidAndWtx.second.GetDepthInMainChain(pIndex) > 0 && pIndex->GetHeight() <= deleteSpentFrom)
2888                                         {
2889                                             continue;
2890                                         }
2891
2892                                         txnouttype txType;
2893                                         std::vector<CTxDestination> addresses;
2894                                         int minSigs;
2895                                         bool eraseTx = true;
2896                                         int i = 0;
2897                                         uint256 hashTx = txidAndWtx.second.GetHash();
2898
2899                                         // if we still have z-address notes on the transaction, don't delete
2900                                         auto sprNoteData = FindMySproutNotes(txidAndWtx.second);
2901                                         auto sapNoteDataAndAddressesToAdd = FindMySaplingNotes(txidAndWtx.second);
2902                                         if (sprNoteData.size() || sapNoteDataAndAddressesToAdd.first.size())
2903                                         {
2904                                             // don't erase the tx, but check to erase IDs
2905                                             eraseTx = false;
2906                                         }
2907
2908                                         // if the tx is spending from another in this wallet, we will not erase it
2909                                         // but check destinations before deciding not to erase IDs
2910                                         if (IsFromMe(txidAndWtx.second, deleteSpentFrom - 1))
2911                                         {
2912                                             eraseTx = false;
2913                                         }
2914
2915                                         // look for a reason not to delete this tx or IDs it is sent to
2916                                         for (auto txout : txidAndWtx.second.vout)
2917                                         {
2918                                             // we only want to remove UTXOs that are sent to this ID, used to be ours, and are no longer cansign
2919                                             if (!txout.scriptPubKey.IsPayToCryptoCondition() || IsSpent(hashTx, i))
2920                                             {
2921                                                 // if this is ours, we will not erase the tx
2922                                                 // we already checked IsFromMe
2923                                                 if (IsMine(txout))
2924                                                 {
2925                                                     eraseTx = false;
2926                                                     continue;
2927                                                 }
2928                                             }
2929                                             bool canSignOut = false;
2930                                             bool canSpendOut = false;
2931
2932                                             if (ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs, this, &canSignOut, &canSpendOut, nHeight == 0 ? INT_MAX : nHeight + 1))
2933                                             {
2934                                                 if (canSignOut || canSpendOut)
2935                                                 {
2936                                                     // we should keep this transaction anyhow, check next
2937                                                     eraseTx = false;
2938                                                     continue;
2939                                                 }
2940
2941                                                 for (auto &dest : addresses)
2942                                                 {
2943                                                     if (dest.which() == COptCCParams::ADDRTYPE_ID)
2944                                                     {
2945                                                         idsToCheck.insert(GetDestinationID(dest));
2946                                                     }
2947                                                 }
2948                                             }
2949
2950                                             i++;
2951                                         }
2952                                         if (eraseTx)
2953                                         {
2954                                             txesToErase.insert(make_pair(&txidAndWtx.first, &txidAndWtx.second));
2955                                         }
2956                                     }
2957
2958                                     for (auto &oneTx : txesToErase)
2959                                     {
2960                                         EraseFromWallet(*oneTx.first);
2961                                     }
2962
2963                                     if (pblock && idsToCheck.count(idID))
2964                                     {
2965                                         // do not remove the current identity that was just added to take away our authority
2966                                         // that is an important record to keep
2967                                         idsToCheck.erase(idID);
2968                                     }
2969
2970                                     // now, we've deleted all transactions that were only in the wallet due to our ability to sign with the ID we just lost
2971                                     // loop through all transactions and remove all IDs found in the remaining transactions from our idsToCheck set after we 
2972                                     // have gone through all wallet transactions, we can delete all IDs remaining in the idsToCheck set
2973                                     // that are not on manual hold
2974                                     for (auto &txidAndWtx : mapWallet)
2975                                     {
2976                                         for (auto txout : txidAndWtx.second.vout)
2977                                         {
2978                                             if (!txout.scriptPubKey.IsPayToCryptoCondition())
2979                                             {
2980                                                 continue;
2981                                             }
2982                                             bool canSignOut = false;
2983                                             bool canSpendOut = false;
2984                                             txnouttype txType;
2985                                             std::vector<CTxDestination> addresses;
2986                                             int minSigs;
2987                                             if (ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs, this, &canSignOut, &canSpendOut, nHeight == 0 ? INT_MAX : nHeight + 1))
2988                                             {
2989                                                 if (canSignOut || canSpendOut)
2990                                                 {
2991                                                     for (auto &dest : addresses)
2992                                                     {
2993                                                         if (dest.which() == COptCCParams::ADDRTYPE_ID)
2994                                                         {
2995                                                             idsToCheck.erase(GetDestinationID(dest));
2996                                                             if (!idsToCheck.size())
2997                                                             {
2998                                                                 break;
2999                                                             }
3000                                                         }
3001                                                     }
3002                                                 }                                                
3003                                             }
3004                                             if (!idsToCheck.size())
3005                                             {
3006                                                 break;
3007                                             }
3008                                         }
3009                                         if (!idsToCheck.size())
3010                                         {
3011                                             break;
3012                                         }
3013                                     }
3014
3015                                     // delete all remaining IDs that are not held for manual hold
3016                                     for (auto &idToRemove : idsToCheck)
3017                                     {
3018                                         std::pair<CIdentityMapKey, CIdentityMapValue> identityToRemove;
3019
3020                                         // if not cansign or canspend, no transactions we care about relating to it and no manual hold, delete the ID from the wallet
3021                                         // also keep the first transition after one we will keep
3022                                         if (GetIdentity(idToRemove, identityToRemove) && 
3023                                             !((identityToRemove.first.flags & (identityToRemove.first.CAN_SIGN + identityToRemove.first.CAN_SPEND)) || identityToRemove.first.flags & identityToRemove.first.MANUAL_HOLD))
3024                                         {
3025                                             std::pair<CIdentityMapKey, CIdentityMapValue> priorIdentity;
3026
3027                                             if (!GetPriorIdentity(identityToRemove.first, priorIdentity) ||
3028                                                 !((priorIdentity.first.flags & (priorIdentity.first.CAN_SIGN + priorIdentity.first.CAN_SPEND)) || identityToRemove.first.flags & identityToRemove.first.MANUAL_HOLD))
3029                                             {
3030                                                 // if we don't have recovery on a revoked ID in our wallet, then remove it
3031                                                 std::pair<CIdentityMapKey, CIdentityMapValue> recoveryIdentity;
3032                                                 if (!identityToRemove.second.IsRevoked() || !GetIdentity(identityToRemove.second.recoveryAuthority, recoveryIdentity) || !(recoveryIdentity.first.flags & recoveryIdentity.first.CAN_SIGN))
3033                                                 {
3034                                                     RemoveIdentity(CIdentityMapKey(idToRemove));
3035                                                 }
3036                                             }
3037                                         }
3038                                     }
3039                                 }
3040                             }
3041                         }
3042                     }
3043                 }
3044             }
3045         }
3046
3047         // for IsMine, the default height is max, not 0
3048         nHeight = nHeight == 0 ? INT_MAX : nHeight;
3049         if (fExisted || IsMine(tx, nHeight) || IsFromMe(tx, nHeight) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0)
3050         {
3051             CWalletTx wtx(this, tx);
3052
3053             if (sproutNoteData.size() > 0) {
3054                 wtx.SetSproutNoteData(sproutNoteData);
3055             }
3056
3057             if (saplingNoteData.size() > 0) {
3058                 wtx.SetSaplingNoteData(saplingNoteData);
3059             }
3060
3061             // Get merkle branch if transaction was found in a block
3062             if (pblock)
3063                 wtx.SetMerkleBranch(*pblock);
3064
3065             // Do not flush the wallet here for performance reasons
3066             // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
3067             CWalletDB walletdb(strWalletFile, "r+", false);
3068
3069             return AddToWallet(wtx, false, &walletdb);
3070         }
3071     }
3072     return false;
3073 }
3074
3075 void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
3076 {
3077     LOCK(cs_wallet);
3078     if (!AddToWalletIfInvolvingMe(tx, pblock, true))
3079         return; // Not one of ours
3080
3081     MarkAffectedTransactionsDirty(tx);
3082 }
3083
3084 void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx)
3085 {
3086     // If a transaction changes 'conflicted' state, that changes the balance
3087     // available of the outputs it spends. So force those to be
3088     // recomputed, also:
3089     BOOST_FOREACH(const CTxIn& txin, tx.vin)
3090     {
3091         if (mapWallet.count(txin.prevout.hash))
3092             mapWallet[txin.prevout.hash].MarkDirty();
3093     }
3094     for (const JSDescription& jsdesc : tx.vJoinSplit) {
3095         for (const uint256& nullifier : jsdesc.nullifiers) {
3096             if (mapSproutNullifiersToNotes.count(nullifier) &&
3097                 mapWallet.count(mapSproutNullifiersToNotes[nullifier].hash)) {
3098                 mapWallet[mapSproutNullifiersToNotes[nullifier].hash].MarkDirty();
3099             }
3100         }
3101     }
3102
3103     for (const SpendDescription &spend : tx.vShieldedSpend) {
3104         uint256 nullifier = spend.nullifier;
3105         if (mapSaplingNullifiersToNotes.count(nullifier) &&
3106             mapWallet.count(mapSaplingNullifiersToNotes[nullifier].hash)) {
3107             mapWallet[mapSaplingNullifiersToNotes[nullifier].hash].MarkDirty();
3108         }
3109     }
3110 }
3111
3112 void CWallet::EraseFromWallet(const uint256 &hash)
3113 {
3114     if (!fFileBacked)
3115         return;
3116     {
3117         LOCK(cs_wallet);
3118         if (mapWallet.erase(hash))
3119             CWalletDB(strWalletFile).EraseTx(hash);
3120     }
3121     return;
3122 }
3123
3124 void CWallet::RescanWallet()
3125 {
3126     if (needsRescan)
3127     {
3128         CBlockIndex *start = chainActive.Height() > 0 ? chainActive[1] : NULL;
3129         if (start)
3130             ScanForWalletTransactions(start, true);
3131         needsRescan = false;
3132     }
3133 }
3134
3135
3136 /**
3137  * Returns a nullifier if the SpendingKey is available
3138  * Throws std::runtime_error if the decryptor doesn't match this note
3139  */
3140 boost::optional<uint256> CWallet::GetSproutNoteNullifier(const JSDescription &jsdesc,
3141                                                          const libzcash::SproutPaymentAddress &address,
3142                                                          const ZCNoteDecryption &dec,
3143                                                          const uint256 &hSig,
3144                                                          uint8_t n) const
3145 {
3146     boost::optional<uint256> ret;
3147     auto note_pt = libzcash::SproutNotePlaintext::decrypt(
3148         dec,
3149         jsdesc.ciphertexts[n],
3150         jsdesc.ephemeralKey,
3151         hSig,
3152         (unsigned char) n);
3153     auto note = note_pt.note(address);
3154
3155     // Check note plaintext against note commitment
3156     if (note.cm() != jsdesc.commitments[n]) {
3157         throw libzcash::note_decryption_failed();
3158     }
3159
3160     // SpendingKeys are only available if:
3161     // - We have them (this isn't a viewing key)
3162     // - The wallet is unlocked
3163     libzcash::SproutSpendingKey key;
3164     if (GetSproutSpendingKey(address, key)) {
3165         ret = note.nullifier(key);
3166     }
3167     return ret;
3168 }
3169
3170 /**
3171  * Finds all output notes in the given transaction that have been sent to
3172  * PaymentAddresses in this wallet.
3173  *
3174  * It should never be necessary to call this method with a CWalletTx, because
3175  * the result of FindMySproutNotes (for the addresses available at the time) will
3176  * already have been cached in CWalletTx.mapSproutNoteData.
3177  */
3178 mapSproutNoteData_t CWallet::FindMySproutNotes(const CTransaction &tx) const
3179 {
3180     LOCK(cs_SpendingKeyStore);
3181     uint256 hash = tx.GetHash();
3182
3183     mapSproutNoteData_t noteData;
3184     for (size_t i = 0; i < tx.vJoinSplit.size(); i++) {
3185         auto hSig = tx.vJoinSplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey);
3186         for (uint8_t j = 0; j < tx.vJoinSplit[i].ciphertexts.size(); j++) {
3187             for (const NoteDecryptorMap::value_type& item : mapNoteDecryptors) {
3188                 try {
3189                     auto address = item.first;
3190                     JSOutPoint jsoutpt {hash, i, j};
3191                     auto nullifier = GetSproutNoteNullifier(
3192                         tx.vJoinSplit[i],
3193                         address,
3194                         item.second,
3195                         hSig, j);
3196                     if (nullifier) {
3197                         SproutNoteData nd {address, *nullifier};
3198                         noteData.insert(std::make_pair(jsoutpt, nd));
3199                     } else {
3200                         SproutNoteData nd {address};
3201                         noteData.insert(std::make_pair(jsoutpt, nd));
3202                     }
3203                     break;
3204                 } catch (const note_decryption_failed &err) {
3205                     // Couldn't decrypt with this decryptor
3206                 } catch (const std::exception &exc) {
3207                     // Unexpected failure
3208                     LogPrintf("FindMySproutNotes(): Unexpected error while testing decrypt:\n");
3209                     LogPrintf("%s\n", exc.what());
3210                 }
3211             }
3212         }
3213     }
3214     return noteData;
3215 }
3216
3217
3218 /**
3219  * Finds all output notes in the given transaction that have been sent to
3220  * SaplingPaymentAddresses in this wallet.
3221  *
3222  * It should never be necessary to call this method with a CWalletTx, because
3223  * the result of FindMySaplingNotes (for the addresses available at the time) will
3224  * already have been cached in CWalletTx.mapSaplingNoteData.
3225  */
3226 std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySaplingNotes(const CTransaction &tx) const
3227 {
3228     LOCK(cs_SpendingKeyStore);
3229     uint256 hash = tx.GetHash();
3230
3231     mapSaplingNoteData_t noteData;
3232     SaplingIncomingViewingKeyMap viewingKeysToAdd;
3233
3234     // Protocol Spec: 4.19 Block Chain Scanning (Sapling)
3235     for (uint32_t i = 0; i < tx.vShieldedOutput.size(); ++i) {
3236         const OutputDescription output = tx.vShieldedOutput[i];
3237         for (auto it = mapSaplingFullViewingKeys.begin(); it != mapSaplingFullViewingKeys.end(); ++it) {
3238             SaplingIncomingViewingKey ivk = it->first;
3239             auto result = SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cm);
3240             if (!result) {
3241                 continue;
3242             }
3243             auto address = ivk.address(result.get().d);
3244             if (address && mapSaplingIncomingViewingKeys.count(address.get()) == 0) {
3245                 viewingKeysToAdd[address.get()] = ivk;
3246             }
3247             // We don't cache the nullifier here as computing it requires knowledge of the note position
3248             // in the commitment tree, which can only be determined when the transaction has been mined.
3249             SaplingOutPoint op {hash, i};
3250             SaplingNoteData nd;
3251             nd.ivk = ivk;
3252             noteData.insert(std::make_pair(op, nd));
3253             break;
3254         }
3255     }
3256
3257     return std::make_pair(noteData, viewingKeysToAdd);
3258 }
3259
3260 bool CWallet::IsSproutNullifierFromMe(const uint256& nullifier) const
3261 {
3262     {
3263         LOCK(cs_wallet);
3264         if (mapSproutNullifiersToNotes.count(nullifier) &&
3265                 mapWallet.count(mapSproutNullifiersToNotes.at(nullifier).hash)) {
3266             return true;
3267         }
3268     }
3269     return false;
3270 }
3271
3272 bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const
3273 {
3274     {
3275         LOCK(cs_wallet);
3276         if (mapSaplingNullifiersToNotes.count(nullifier) &&
3277                 mapWallet.count(mapSaplingNullifiersToNotes.at(nullifier).hash)) {
3278             return true;
3279         }
3280     }
3281     return false;
3282 }
3283
3284 void CWallet::GetSproutNoteWitnesses(std::vector<JSOutPoint> notes,
3285                                      std::vector<boost::optional<SproutWitness>>& witnesses,
3286                                      uint256 &final_anchor)
3287 {
3288     LOCK(cs_wallet);
3289     witnesses.resize(notes.size());
3290     boost::optional<uint256> rt;
3291     int i = 0;
3292     for (JSOutPoint note : notes) {
3293         if (mapWallet.count(note.hash) &&
3294                 mapWallet[note.hash].mapSproutNoteData.count(note) &&
3295                 mapWallet[note.hash].mapSproutNoteData[note].witnesses.size() > 0) {
3296             witnesses[i] = mapWallet[note.hash].mapSproutNoteData[note].witnesses.front();
3297             if (!rt) {
3298                 rt = witnesses[i]->root();
3299             } else {
3300                 assert(*rt == witnesses[i]->root());
3301             }
3302         }
3303         i++;
3304     }
3305     // All returned witnesses have the same anchor
3306     if (rt) {
3307         final_anchor = *rt;
3308     }
3309 }
3310
3311 void CWallet::GetSaplingNoteWitnesses(std::vector<SaplingOutPoint> notes,
3312                                       std::vector<boost::optional<SaplingWitness>>& witnesses,
3313                                       uint256 &final_anchor)
3314 {
3315     LOCK(cs_wallet);
3316     witnesses.resize(notes.size());
3317     boost::optional<uint256> rt;
3318     int i = 0;
3319     for (SaplingOutPoint note : notes) {
3320         if (mapWallet.count(note.hash) &&
3321                 mapWallet[note.hash].mapSaplingNoteData.count(note) &&
3322                 mapWallet[note.hash].mapSaplingNoteData[note].witnesses.size() > 0) {
3323             witnesses[i] = mapWallet[note.hash].mapSaplingNoteData[note].witnesses.front();
3324             if (!rt) {
3325                 rt = witnesses[i]->root();
3326             } else {
3327                 assert(*rt == witnesses[i]->root());
3328             }
3329         }
3330         i++;
3331     }
3332     // All returned witnesses have the same anchor
3333     if (rt) {
3334         final_anchor = *rt;
3335     }
3336 }
3337
3338 isminetype CWallet::IsMine(const CTxIn &txin, uint32_t nHeight) const
3339 {
3340     {
3341         LOCK(cs_wallet);
3342         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3343         if (mi != mapWallet.end())
3344         {
3345             const CWalletTx& prev = (*mi).second;
3346             if (txin.prevout.n < prev.vout.size())
3347                 return (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey, nHeight));
3348         }
3349     }
3350     return ISMINE_NO;
3351 }
3352
3353 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter, uint32_t nHeight) const
3354 {
3355     {
3356         LOCK(cs_wallet);
3357         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3358         if (mi != mapWallet.end())
3359         {
3360             const CWalletTx& prev = (*mi).second;
3361             if (txin.prevout.n < prev.vout.size())
3362                 if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey, nHeight) & filter)
3363                     return prev.vout[txin.prevout.n].nValue; // komodo_interest?
3364         }
3365     }
3366     return 0;
3367 }
3368
3369 CCurrencyValueMap CWallet::GetReserveDebit(const CTxIn &txin, const isminefilter& filter, uint32_t nHeight) const
3370 {
3371     {
3372         LOCK(cs_wallet);
3373         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3374         if (mi != mapWallet.end())
3375         {
3376             const CWalletTx& prev = (*mi).second;
3377             if (txin.prevout.n < prev.vout.size())
3378                 if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey, nHeight) & filter)
3379                     return prev.vout[txin.prevout.n].ReserveOutValue();
3380         }
3381     }
3382     return CCurrencyValueMap();
3383 }
3384
3385 isminetype CWallet::IsMine(const CTxOut& txout, uint32_t nHeight) const
3386 {
3387     return ::IsMine(*this, txout.scriptPubKey, nHeight);
3388 }
3389
3390 CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter, uint32_t nHeight) const
3391 {
3392     if (!MoneyRange(txout.nValue))
3393         throw std::runtime_error("CWallet::GetCredit(): value out of range");
3394     return ((IsMine(txout, nHeight) & filter) ? txout.nValue : 0);
3395 }
3396
3397 bool CWallet::IsChange(const CTxOut& txout) const
3398 {
3399     // TODO: fix handling of 'change' outputs. The assumption is that any
3400     // payment to a script that is ours, but is not in the address book
3401     // is change. That assumption is likely to break when we implement multisignature
3402     // wallets that return change back into a multi-signature-protected address;
3403     // a better way of identifying which outputs are 'the send' and which are
3404     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
3405     // which output, if any, was change).
3406     if (::IsMine(*this, txout.scriptPubKey))
3407     {
3408         CTxDestination address;
3409         if (!ExtractDestination(txout.scriptPubKey, address))
3410             return true;
3411
3412         LOCK(cs_wallet);
3413         if (!mapAddressBook.count(address))
3414             return true;
3415     }
3416     return false;
3417 }
3418
3419 CAmount CWallet::GetChange(const CTxOut& txout) const
3420 {
3421     if (!MoneyRange(txout.nValue))
3422         throw std::runtime_error("CWallet::GetChange(): value out of range");
3423     return (IsChange(txout) ? txout.nValue : 0);
3424 }
3425
3426 typedef vector<unsigned char> valtype;
3427 unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore);
3428
3429 bool CWallet::IsMine(const CTransaction& tx, uint32_t nHeight)
3430 {
3431     for (int i = 0; i < tx.vout.size(); i++)
3432     {
3433         isminetype mine;
3434         IsMine(tx, i, mine, nHeight);
3435         if (mine)
3436             return true;
3437     }
3438     return false;
3439 }
3440
3441 // special case handling for non-standard/Verus OP_RETURN script outputs, which need the transaction
3442 // to determine ownership
3443 void CWallet::IsMine(const CTransaction& tx, uint32_t voutNum, isminetype &mine, uint32_t nHeight)
3444 {
3445     vector<valtype> vSolutions;
3446     txnouttype whichType;
3447     CScript scriptPubKey = tx.vout[voutNum].scriptPubKey;
3448
3449     if (scriptPubKey.IsCheckLockTimeVerify())
3450     {
3451         uint8_t pushOp = scriptPubKey[0];
3452         uint32_t scriptStart = pushOp + 3;
3453
3454         // continue with post CLTV script
3455         scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end());
3456     }
3457
3458     COptCCParams p;
3459     if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
3460     {
3461         std::vector<CTxDestination> dests;
3462         int minSigs;
3463         bool canSign = false;
3464         bool canSpend = false;
3465
3466         if (ExtractDestinations(scriptPubKey, whichType, dests, minSigs, this, &canSign, &canSpend, nHeight))
3467         {
3468             if (canSpend)
3469             {
3470                 mine = ISMINE_SPENDABLE;
3471                 return;
3472             }
3473             else if (canSign)
3474             {
3475                 mine = ISMINE_WATCH_ONLY;
3476                 return;
3477             }
3478             else
3479             {
3480                 mine = ISMINE_NO;
3481                 return;
3482             }
3483         }
3484         else
3485         {
3486             mine = ISMINE_NO;
3487             return;
3488         }
3489     }
3490     else if (!Solver(scriptPubKey, whichType, vSolutions))
3491     {
3492         if (this->HaveWatchOnly(scriptPubKey))
3493         {
3494             mine = ISMINE_WATCH_ONLY;
3495             return;
3496         }
3497         mine = ISMINE_NO;
3498         return;
3499     }
3500
3501     CKeyID keyID;
3502     CScriptID scriptID;
3503     CScriptExt subscript;
3504     int voutNext = voutNum + 1;
3505
3506     switch (whichType)
3507     {
3508         case TX_NONSTANDARD:
3509         case TX_NULL_DATA:
3510             break;
3511
3512         case TX_CRYPTOCONDITION:
3513             // for now, default is that the first value returned will be the target address, subsequent values will be
3514             // pubkeys. if we have the first in our wallet, we consider it spendable for now
3515             if (vSolutions[0].size() == 33)
3516             {
3517                 keyID = CPubKey(vSolutions[0]).GetID();
3518             }
3519             else if (vSolutions[0].size() == 20)
3520             {
3521                 keyID = CKeyID(uint160(vSolutions[0]));
3522             }
3523             if (!keyID.IsNull() && HaveKey(keyID))
3524             {
3525                 mine = ISMINE_SPENDABLE;
3526                 return;
3527             }
3528             break;
3529
3530         case TX_PUBKEY:
3531             keyID = CPubKey(vSolutions[0]).GetID();
3532             if (this->HaveKey(keyID))
3533             {
3534                 mine = ISMINE_SPENDABLE;
3535                 return;
3536             }
3537             break;
3538
3539         case TX_PUBKEYHASH:
3540             keyID = CKeyID(uint160(vSolutions[0]));
3541             if (this->HaveKey(keyID))
3542             {
3543                 mine = ISMINE_SPENDABLE;
3544                 return;
3545             }
3546             break;
3547
3548         case TX_SCRIPTHASH:
3549             scriptID = CScriptID(uint160(vSolutions[0]));
3550             if (this->GetCScript(scriptID, subscript)) 
3551             {
3552                 // if this is a CLTV, handle it differently
3553                 if (subscript.IsCheckLockTimeVerify())
3554                 {
3555                     mine = (::IsMine(*this, subscript));
3556                     return;
3557                 }
3558                 else
3559                 {
3560                     isminetype ret = ::IsMine(*this, subscript);
3561                     if (ret == ISMINE_SPENDABLE)
3562                     {
3563                         mine = ret;
3564                         return;
3565                     }
3566                 }
3567             }
3568             else if (tx.vout.size() > (voutNum + 1) &&
3569                 tx.vout.back().scriptPubKey.size() > 7 &&
3570                 tx.vout.back().scriptPubKey[0] == OP_RETURN)
3571             {
3572                 // get the opret script from next vout, verify that the front is CLTV and hash matches
3573                 // if so, remove it and use the solver
3574                 opcodetype op;
3575                 std::vector<uint8_t> opretData;
3576                 CScript::const_iterator it = tx.vout.back().scriptPubKey.begin() + 1;
3577                 if (tx.vout.back().scriptPubKey.GetOp2(it, op, &opretData))
3578                 {
3579                     if (opretData.size() > 0 && opretData[0] == OPRETTYPE_TIMELOCK)
3580                     {
3581                         CScript opretScript = CScript(opretData.begin() + 1, opretData.end());
3582
3583                         if (CScriptID(opretScript) == scriptID &&
3584                             opretScript.IsCheckLockTimeVerify())
3585                         {
3586                             // if we find that this is ours, we need to add this script to the wallet,
3587                             // and we can then recognize this transaction
3588                             isminetype t = ::IsMine(*this, opretScript);
3589                             if (t != ISMINE_NO)
3590                             {
3591                                 this->AddCScript(opretScript);
3592                             }
3593                             mine = t;
3594                             return;
3595                         }
3596                     }
3597                 }
3598             }
3599             break;
3600
3601         case TX_MULTISIG:
3602             // Only consider transactions "mine" if we own ALL the
3603             // keys involved. Multi-signature transactions that are
3604             // partially owned (somebody else has a key that can spend
3605             // them) enable spend-out-from-under-you attacks, especially
3606             // in shared-wallet situations.
3607             vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
3608             if (HaveKeys(keys, *this) == keys.size())
3609             {
3610                 mine = ISMINE_SPENDABLE;
3611                 return;
3612             }
3613             break;
3614     }
3615
3616     if (this->HaveWatchOnly(scriptPubKey))
3617     {
3618         mine = ISMINE_WATCH_ONLY;
3619         return;
3620     }
3621
3622     mine = ISMINE_NO;
3623 }
3624
3625 bool CWallet::IsFromMe(const CTransaction& tx, uint32_t height) const
3626 {
3627     {
3628         LOCK(cs_wallet);
3629         for (auto &txin : tx.vin)
3630         {
3631             map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3632             if (mi != mapWallet.end())
3633             {
3634                 const CWalletTx& prev = (*mi).second;
3635                 if (txin.prevout.n < prev.vout.size())
3636                 {
3637                     if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey, height) & ISMINE_ALL)
3638                         return true;
3639                 }
3640             }
3641         }
3642     }
3643     for (const JSDescription& jsdesc : tx.vJoinSplit) {
3644         for (const uint256& nullifier : jsdesc.nullifiers) {
3645             if (IsSproutNullifierFromMe(nullifier)) {
3646                 return true;
3647             }
3648         }
3649     }
3650     for (const SpendDescription &spend : tx.vShieldedSpend) {
3651         if (IsSaplingNullifierFromMe(spend.nullifier)) {
3652             return true;
3653         }
3654     }
3655     return false;
3656 }
3657
3658 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3659 {
3660     CAmount nDebit = 0;
3661     BOOST_FOREACH(const CTxIn& txin, tx.vin)
3662     {
3663         nDebit += GetDebit(txin, filter, nHeight);
3664         if (!MoneyRange(nDebit))
3665             throw std::runtime_error("CWallet::GetDebit(): value out of range");
3666     }
3667     return nDebit;
3668 }
3669
3670 CCurrencyValueMap CWallet::GetReserveDebit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3671 {
3672     CCurrencyValueMap retVal;
3673     BOOST_FOREACH(const CTxIn& txin, tx.vin)
3674     {
3675         retVal += GetReserveDebit(txin, filter, nHeight);
3676     }
3677     return retVal;
3678 }
3679
3680 CAmount CWallet::GetCredit(const CTransaction& tx, const int32_t &voutNum, const isminefilter& filter, uint32_t nHeight) const
3681 {
3682     if (voutNum >= tx.vout.size() || !MoneyRange(tx.vout[voutNum].nValue))
3683         throw std::runtime_error("CWallet::GetCredit(): value out of range");
3684     return ((IsMine(tx.vout[voutNum], nHeight) & filter) ? tx.vout[voutNum].nValue : 0);
3685 }
3686
3687 CCurrencyValueMap CWallet::GetReserveCredit(const CTransaction& tx, int32_t voutNum, const isminefilter& filter) const
3688 {
3689     return ((IsMine(tx.vout[voutNum]) & filter) ? tx.vout[voutNum].ReserveOutValue() : CCurrencyValueMap());
3690 }
3691
3692 CCurrencyValueMap CWallet::GetReserveCredit(const CTransaction& tx, const isminefilter& filter) const
3693 {
3694     CCurrencyValueMap nCredit;
3695     for (int i = 0; i < tx.vout.size(); i++)
3696     {
3697         nCredit += GetReserveCredit(tx, i, filter);
3698     }
3699     return nCredit;
3700 }
3701
3702 CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3703 {
3704     CAmount nCredit = 0;
3705     for (int i = 0; i < tx.vout.size(); i++)
3706     {
3707         nCredit += GetCredit(tx, i, filter, nHeight);
3708     }
3709     return nCredit;
3710 }
3711
3712 CAmount CWallet::GetChange(const CTransaction& tx) const
3713 {
3714     CAmount nChange = 0;
3715     BOOST_FOREACH(const CTxOut& txout, tx.vout)
3716     {
3717         nChange += GetChange(txout);
3718         if (!MoneyRange(nChange))
3719             throw std::runtime_error("CWallet::GetChange(): value out of range");
3720     }
3721     return nChange;
3722 }
3723
3724 bool CWallet::IsHDFullyEnabled() const
3725 {
3726     // Only Sapling addresses are HD for now
3727     return false;
3728 }
3729
3730 void CWallet::GenerateNewSeed()
3731 {
3732     LOCK(cs_wallet);
3733
3734     auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
3735
3736     int64_t nCreationTime = GetTime();
3737
3738     // If the wallet is encrypted and locked, this will fail.
3739     if (!SetHDSeed(seed))
3740         throw std::runtime_error(std::string(__func__) + ": SetHDSeed failed");
3741
3742     // store the key creation time together with
3743     // the child index counter in the database
3744     // as a hdchain object
3745     CHDChain newHdChain;
3746     newHdChain.nVersion = CHDChain::VERSION_HD_BASE;
3747     newHdChain.seedFp = seed.Fingerprint();
3748     newHdChain.nCreateTime = nCreationTime;
3749     SetHDChain(newHdChain, false);
3750 }
3751
3752 bool CWallet::SetHDSeed(const HDSeed& seed)
3753 {
3754     if (!CCryptoKeyStore::SetHDSeed(seed)) {
3755         return false;
3756     }
3757
3758     if (!fFileBacked) {
3759         return true;
3760     }
3761
3762     {
3763         LOCK(cs_wallet);
3764         if (!IsCrypted()) {
3765             return CWalletDB(strWalletFile).WriteHDSeed(seed);
3766         }
3767     }
3768     return true;
3769 }
3770
3771 bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
3772 {
3773     if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
3774         return false;
3775     }
3776
3777     if (!fFileBacked) {
3778         return true;
3779     }
3780
3781     {
3782         LOCK(cs_wallet);
3783         if (pwalletdbEncryption)
3784             return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
3785         else
3786             return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
3787     }
3788     return false;
3789 }
3790
3791 HDSeed CWallet::GetHDSeedForRPC() const {
3792     HDSeed seed;
3793     if (!pwalletMain->GetHDSeed(seed)) {
3794         throw JSONRPCError(RPC_WALLET_ERROR, "HD seed not found");
3795     }
3796     return seed;
3797 }
3798
3799 void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
3800 {
3801     LOCK(cs_wallet);
3802     if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
3803         throw std::runtime_error(std::string(__func__) + ": writing chain failed");
3804
3805     hdChain = chain;
3806 }
3807
3808 bool CWallet::LoadHDSeed(const HDSeed& seed)
3809 {
3810     return CBasicKeyStore::SetHDSeed(seed);
3811 }
3812
3813 bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
3814 {
3815     return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
3816 }
3817
3818 void CWalletTx::SetSproutNoteData(mapSproutNoteData_t &noteData)
3819 {
3820     mapSproutNoteData.clear();
3821     for (const std::pair<JSOutPoint, SproutNoteData> nd : noteData) {
3822         if (nd.first.js < vJoinSplit.size() &&
3823                 nd.first.n < vJoinSplit[nd.first.js].ciphertexts.size()) {
3824             // Store the address and nullifier for the Note
3825             mapSproutNoteData[nd.first] = nd.second;
3826         } else {
3827             // If FindMySproutNotes() was used to obtain noteData,
3828             // this should never happen
3829             throw std::logic_error("CWalletTx::SetSproutNoteData(): Invalid note");
3830         }
3831     }
3832 }
3833
3834 void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t &noteData)
3835 {
3836     mapSaplingNoteData.clear();
3837     for (const std::pair<SaplingOutPoint, SaplingNoteData> nd : noteData) {
3838         if (nd.first.n < vShieldedOutput.size()) {
3839             mapSaplingNoteData[nd.first] = nd.second;
3840         } else {
3841             throw std::logic_error("CWalletTx::SetSaplingNoteData(): Invalid note");
3842         }
3843     }
3844 }
3845
3846 std::pair<SproutNotePlaintext, SproutPaymentAddress> CWalletTx::DecryptSproutNote(
3847     JSOutPoint jsop) const
3848 {
3849     LOCK(pwallet->cs_wallet);
3850
3851     auto nd = this->mapSproutNoteData.at(jsop);
3852     SproutPaymentAddress pa = nd.address;
3853
3854     // Get cached decryptor
3855     ZCNoteDecryption decryptor;
3856     if (!pwallet->GetNoteDecryptor(pa, decryptor)) {
3857         // Note decryptors are created when the wallet is loaded, so it should always exist
3858         throw std::runtime_error(strprintf(
3859             "Could not find note decryptor for payment address %s",
3860             EncodePaymentAddress(pa)));
3861     }
3862
3863     auto hSig = this->vJoinSplit[jsop.js].h_sig(*pzcashParams, this->joinSplitPubKey);
3864     try {
3865         SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
3866                 decryptor,
3867                 this->vJoinSplit[jsop.js].ciphertexts[jsop.n],
3868                 this->vJoinSplit[jsop.js].ephemeralKey,
3869                 hSig,
3870                 (unsigned char) jsop.n);
3871
3872         return std::make_pair(plaintext, pa);
3873     } catch (const note_decryption_failed &err) {
3874         // Couldn't decrypt with this spending key
3875         throw std::runtime_error(strprintf(
3876             "Could not decrypt note for payment address %s",
3877             EncodePaymentAddress(pa)));
3878     } catch (const std::exception &exc) {
3879         // Unexpected failure
3880         throw std::runtime_error(strprintf(
3881             "Error while decrypting note for payment address %s: %s",
3882             EncodePaymentAddress(pa), exc.what()));
3883     }
3884 }
3885
3886 boost::optional<std::pair<
3887     SaplingNotePlaintext,
3888     SaplingPaymentAddress>> CWalletTx::DecryptSaplingNote(SaplingOutPoint op) const
3889 {
3890     // Check whether we can decrypt this SaplingOutPoint
3891     if (this->mapSaplingNoteData.count(op) == 0) {
3892         return boost::none;
3893     }
3894
3895     auto output = this->vShieldedOutput[op.n];
3896     auto nd = this->mapSaplingNoteData.at(op);
3897
3898     auto maybe_pt = SaplingNotePlaintext::decrypt(
3899         output.encCiphertext,
3900         nd.ivk,
3901         output.ephemeralKey,
3902         output.cm);
3903     assert(static_cast<bool>(maybe_pt));
3904     auto notePt = maybe_pt.get();
3905
3906     auto maybe_pa = nd.ivk.address(notePt.d);
3907     assert(static_cast<bool>(maybe_pa));
3908     auto pa = maybe_pa.get();
3909
3910     return std::make_pair(notePt, pa);
3911 }
3912
3913 boost::optional<std::pair<
3914     SaplingNotePlaintext,
3915     SaplingPaymentAddress>> CWalletTx::RecoverSaplingNote(
3916         SaplingOutPoint op, std::set<uint256>& ovks) const
3917 {
3918     auto output = this->vShieldedOutput[op.n];
3919
3920     for (auto ovk : ovks) {
3921         auto outPt = SaplingOutgoingPlaintext::decrypt(
3922             output.outCiphertext,
3923             ovk,
3924             output.cv,
3925             output.cm,
3926             output.ephemeralKey);
3927         if (!outPt) {
3928             continue;
3929         }
3930
3931         auto maybe_pt = SaplingNotePlaintext::decrypt(
3932             output.encCiphertext,
3933             output.ephemeralKey,
3934             outPt->esk,
3935             outPt->pk_d,
3936             output.cm);
3937         assert(static_cast<bool>(maybe_pt));
3938         auto notePt = maybe_pt.get();
3939
3940         return std::make_pair(notePt, SaplingPaymentAddress(notePt.d, outPt->pk_d));
3941     }
3942
3943     // Couldn't recover with any of the provided OutgoingViewingKeys
3944     return boost::none;
3945 }
3946
3947 int64_t CWalletTx::GetTxTime() const
3948 {
3949     int64_t n = nTimeSmart;
3950     return n ? n : nTimeReceived;
3951 }
3952
3953 int CWalletTx::GetRequestCount() const
3954 {
3955     // Returns -1 if it wasn't being tracked
3956     int nRequests = -1;
3957     {
3958         LOCK(pwallet->cs_wallet);
3959         if (IsCoinBase())
3960         {
3961             // Generated block
3962             if (!hashBlock.IsNull())
3963             {
3964                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
3965                 if (mi != pwallet->mapRequestCount.end())
3966                     nRequests = (*mi).second;
3967             }
3968         }
3969         else
3970         {
3971             // Did anyone request this transaction?
3972             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
3973             if (mi != pwallet->mapRequestCount.end())
3974             {
3975                 nRequests = (*mi).second;
3976
3977                 // How about the block it's in?
3978                 if (nRequests == 0 && !hashBlock.IsNull())
3979                 {
3980                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
3981                     if (mi != pwallet->mapRequestCount.end())
3982                         nRequests = (*mi).second;
3983                     else
3984                         nRequests = 1; // If it's in someone else's block it must have got out
3985                 }
3986             }
3987         }
3988     }
3989     return nRequests;
3990 }
3991
3992 // GetAmounts will determine the transparent debits and credits for a given wallet tx.
3993 void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
3994                            list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
3995 {
3996     nFee = 0;
3997     listReceived.clear();
3998     listSent.clear();
3999     strSentAccount = strFromAccount;
4000
4001     // Is this tx sent/signed by me?
4002     CAmount nDebit = GetDebit(filter);
4003
4004     bool isFromMyTaddr = false;
4005
4006     for (auto &txin : vin)
4007     {
4008         map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(txin.prevout.hash);
4009         if (mi != pwallet->mapWallet.end())
4010         {
4011             const CWalletTx& prev = (*mi).second;
4012             if (txin.prevout.n < prev.vout.size())
4013             {
4014                 if (::IsMine(*pwallet, prev.vout[txin.prevout.n].scriptPubKey) & filter)
4015                 {
4016                     isFromMyTaddr = true;
4017                     break;
4018                 }
4019             }
4020         }
4021     }
4022
4023     //bool isFromMyTaddr = pwallet->IsFromMe(*this); // IsFromMe(filter); // debit>0 means we signed/sent this transaction
4024
4025     // Compute fee if we sent this transaction.
4026     if (isFromMyTaddr) {
4027         CAmount nValueOut = GetValueOut();  // transparent outputs plus all Sprout vpub_old and negative Sapling valueBalance
4028         CAmount nValueIn = GetShieldedValueIn();
4029         nFee = nDebit - nValueOut + nValueIn;
4030     }
4031
4032     // Create output entry for vpub_old/new, if we sent utxos from this transaction
4033     if (isFromMyTaddr) {
4034         CAmount myVpubOld = 0;
4035         CAmount myVpubNew = 0;
4036         for (const JSDescription& js : vJoinSplit) {
4037             bool fMyJSDesc = false;
4038
4039             // Check input side
4040             for (const uint256& nullifier : js.nullifiers) {
4041                 if (pwallet->IsSproutNullifierFromMe(nullifier)) {
4042                     fMyJSDesc = true;
4043                     break;
4044                 }
4045             }
4046
4047             // Check output side
4048             if (!fMyJSDesc) {
4049                 for (const std::pair<JSOutPoint, SproutNoteData> nd : this->mapSproutNoteData) {
4050                     if (nd.first.js < vJoinSplit.size() && nd.first.n < vJoinSplit[nd.first.js].ciphertexts.size()) {
4051                         fMyJSDesc = true;
4052                         break;
4053                     }
4054                 }
4055             }
4056
4057             if (fMyJSDesc) {
4058                 myVpubOld += js.vpub_old;
4059                 myVpubNew += js.vpub_new;
4060             }
4061
4062             if (!MoneyRange(js.vpub_old) || !MoneyRange(js.vpub_new) || !MoneyRange(myVpubOld) || !MoneyRange(myVpubNew)) {
4063                  throw std::runtime_error("CWalletTx::GetAmounts: value out of range");
4064             }
4065         }
4066
4067         // Create an output for the value taken from or added to the transparent value pool by JoinSplits
4068         if (myVpubOld > myVpubNew) {
4069             COutputEntry output = {CNoDestination(), myVpubOld - myVpubNew, (int)vout.size()};
4070             listSent.push_back(output);
4071         } else if (myVpubNew > myVpubOld) {
4072             COutputEntry output = {CNoDestination(), myVpubNew - myVpubOld, (int)vout.size()};
4073             listReceived.push_back(output);
4074         }
4075     }
4076
4077     // If we sent utxos from this transaction, create output for value taken from (negative valueBalance)
4078     // or added (positive valueBalance) to the transparent value pool by Sapling shielding and unshielding.
4079     if (isFromMyTaddr) {
4080         if (valueBalance < 0) {
4081             COutputEntry output = {CNoDestination(), -valueBalance, (int) vout.size()};
4082             listSent.push_back(output);
4083         } else if (valueBalance > 0) {
4084             COutputEntry output = {CNoDestination(), valueBalance, (int) vout.size()};
4085             listReceived.push_back(output);
4086         }
4087     }
4088
4089     // Sent/received.
4090     for (unsigned int i = 0; i < vout.size(); ++i)
4091     {
4092         const CTxOut& txout = vout[i];
4093         isminetype fIsMine = pwallet->IsMine(txout);
4094         // Only need to handle txouts if AT LEAST one of these is true:
4095         //   1) they debit from us (sent)
4096         //   2) the output is to us (received)
4097         if (nDebit > 0)
4098         {
4099             // Don't report 'change' txouts
4100             if (!(filter & ISMINE_CHANGE) && pwallet->IsChange(txout))
4101                 continue;
4102         }
4103         else if (!(fIsMine & filter))
4104             continue;
4105
4106         // In either case, we need to get the destination address
4107         CTxDestination address;
4108         if (!ExtractDestination(txout.scriptPubKey, address))
4109         {
4110             //LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",this->GetHash().ToString()); complains on the opreturns
4111             address = CNoDestination();
4112         }
4113
4114         COutputEntry output = {address, txout.nValue, (int)i};
4115
4116         // If we are debited by the transaction, add the output as a "sent" entry
4117         if (nDebit > 0)
4118             listSent.push_back(output);
4119
4120         // If we are receiving the output, add it as a "received" entry
4121         if (fIsMine & filter)
4122             listReceived.push_back(output);
4123     }
4124 }
4125
4126 void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
4127                                   CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
4128 {
4129     nReceived = nSent = nFee = 0;
4130
4131     CAmount allFee;
4132     string strSentAccount;
4133     list<COutputEntry> listReceived;
4134     list<COutputEntry> listSent;
4135     GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
4136
4137     if (strAccount == strSentAccount)
4138     {
4139         BOOST_FOREACH(const COutputEntry& s, listSent)
4140             nSent += s.amount;
4141         nFee = allFee;
4142     }
4143     {
4144         LOCK(pwallet->cs_wallet);
4145         BOOST_FOREACH(const COutputEntry& r, listReceived)
4146         {
4147             if (pwallet->mapAddressBook.count(r.destination))
4148             {
4149                 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
4150                 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
4151                     nReceived += r.amount;
4152             }
4153             else if (strAccount.empty())
4154             {
4155                 nReceived += r.amount;
4156             }
4157         }
4158     }
4159 }
4160
4161
4162 bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
4163 {
4164     return pwalletdb->WriteTx(GetHash(), *this);
4165 }
4166
4167 void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
4168                                     std::vector<boost::optional<SproutWitness>>& witnesses,
4169                                     uint256 &final_anchor)
4170 {
4171     witnesses.resize(commitments.size());
4172     CBlockIndex* pindex = chainActive.Genesis();
4173     SproutMerkleTree tree;
4174
4175     while (pindex) {
4176         CBlock block;
4177         ReadBlockFromDisk(block, pindex, Params().GetConsensus(), 1);
4178
4179         BOOST_FOREACH(const CTransaction& tx, block.vtx)
4180         {
4181             BOOST_FOREACH(const JSDescription& jsdesc, tx.vJoinSplit)
4182             {
4183                 BOOST_FOREACH(const uint256 &note_commitment, jsdesc.commitments)
4184                 {
4185                     tree.append(note_commitment);
4186
4187                     BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
4188                         if (wit) {
4189                             wit->append(note_commitment);
4190                         }
4191                     }
4192
4193                     size_t i = 0;
4194                     BOOST_FOREACH(uint256& commitment, commitments) {
4195                         if (note_commitment == commitment) {
4196                             witnesses.at(i) = tree.witness();
4197                         }
4198                         i++;
4199                     }
4200                 }
4201             }
4202         }
4203
4204         uint256 current_anchor = tree.root();
4205
4206         // Consistency check: we should be able to find the current tree
4207         // in our CCoins view.
4208         SproutMerkleTree dummy_tree;
4209         assert(pcoinsTip->GetSproutAnchorAt(current_anchor, dummy_tree));
4210
4211         pindex = chainActive.Next(pindex);
4212     }
4213
4214     // TODO: #93; Select a root via some heuristic.
4215     final_anchor = tree.root();
4216
4217     BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
4218         if (wit) {
4219             assert(final_anchor == wit->root());
4220         }
4221     }
4222 }
4223
4224 /**
4225  * Scan the block chain (starting in pindexStart) for transactions
4226  * from or to us. If fUpdate is true, found transactions that already
4227  * exist in the wallet will be updated.
4228  */
4229 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
4230 {
4231     int ret = 0;
4232     int64_t nNow = GetTime();
4233     const CChainParams& chainParams = Params();
4234
4235     CBlockIndex* pindex = pindexStart;
4236
4237     std::vector<uint256> myTxHashes;
4238
4239     {
4240         LOCK2(cs_main, cs_wallet);
4241
4242         // no need to read and scan block, if block was created before
4243         // our wallet birthday (as adjusted for block time variability)
4244         while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200)))
4245             pindex = chainActive.Next(pindex);
4246
4247         ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
4248         double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false);
4249         double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip(), false);
4250         while (pindex)
4251         {
4252             if (pindex->GetHeight() % 100 == 0 && dProgressTip - dProgressStart > 0.0)
4253                 ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
4254
4255             CBlock block;
4256             ReadBlockFromDisk(block, pindex, Params().GetConsensus());
4257             BOOST_FOREACH(CTransaction& tx, block.vtx)
4258             {
4259                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
4260                     myTxHashes.push_back(tx.GetHash());
4261                     ret++;
4262                 }
4263             }
4264
4265             SproutMerkleTree sproutTree;
4266             SaplingMerkleTree saplingTree;
4267             // This should never fail: we should always be able to get the tree
4268             // state on the path to the tip of our chain
4269             assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree));
4270             if (pindex->pprev) {
4271                 if (Params().GetConsensus().NetworkUpgradeActive(pindex->pprev->GetHeight(),  Consensus::UPGRADE_SAPLING)) {
4272                     assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree));
4273                 }
4274             }
4275             // Increment note witness caches
4276             ChainTipAdded(pindex, &block, sproutTree, saplingTree);
4277
4278             pindex = chainActive.Next(pindex);
4279             if (GetTime() >= nNow + 60) {
4280                 nNow = GetTime();
4281                 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->GetHeight(), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
4282             }
4283         }
4284
4285         // After rescanning, persist Sapling note data that might have changed, e.g. nullifiers.
4286         // Do not flush the wallet here for performance reasons.
4287         CWalletDB walletdb(strWalletFile, "r+", false);
4288         for (auto hash : myTxHashes) {
4289             CWalletTx wtx = mapWallet[hash];
4290             if (!wtx.mapSaplingNoteData.empty()) {
4291                 if (!wtx.WriteToDisk(&walletdb)) {
4292                     LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString());
4293                 }
4294             }
4295         }
4296
4297         ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
4298     }
4299     return ret;
4300 }
4301
4302 void CWallet::ReacceptWalletTransactions()
4303 {
4304     // If transactions aren't being broadcasted, don't let them into local mempool either
4305     if (!fBroadcastTransactions)
4306         return;
4307     LOCK2(cs_main, cs_wallet);
4308     std::map<int64_t, CWalletTx*> mapSorted;
4309
4310     // Sort pending wallet transactions based on their initial wallet insertion order
4311     BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
4312     {
4313         const uint256& wtxid = item.first;
4314         CWalletTx& wtx = item.second;
4315         assert(wtx.GetHash() == wtxid);
4316
4317         int nDepth = wtx.GetDepthInMainChain();
4318
4319         if (!wtx.IsCoinBase() && nDepth < 0) {
4320             mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
4321         }
4322     }
4323
4324     std::vector<uint256> vwtxh;
4325
4326     // Try to add wallet transactions to memory pool
4327     BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted)
4328     {
4329         CWalletTx& wtx = *(item.second);
4330
4331         LOCK(mempool.cs);
4332         CValidationState state;
4333         // attempt to add them, but don't set any DOS level
4334         if (!::AcceptToMemoryPool(mempool, state, wtx, false, NULL, true, 0))
4335         {
4336             int nDoS;
4337             bool invalid = state.IsInvalid(nDoS);
4338
4339             // log rejection and deletion
4340             // printf("ERROR reaccepting wallet transaction %s to mempool, reason: %s, DoS: %d\n", wtx.GetHash().ToString().c_str(), state.GetRejectReason().c_str(), nDoS);
4341
4342             if (!wtx.IsCoinBase() && invalid && nDoS > 0)
4343             {
4344                 LogPrintf("erasing transaction %s\n", wtx.GetHash().GetHex().c_str());
4345                 vwtxh.push_back(wtx.GetHash());
4346             }
4347         }
4348     }
4349     for (auto hash : vwtxh)
4350     {
4351         EraseFromWallet(hash);
4352     }
4353 }
4354
4355 bool CWalletTx::RelayWalletTransaction()
4356 {
4357     if ( pwallet == 0 )
4358     {
4359         fprintf(stderr,"unexpected null pwallet in RelayWalletTransaction\n");
4360         return(false);
4361     }
4362     assert(pwallet->GetBroadcastTransactions());
4363     if (!IsCoinBase())
4364     {
4365         if (GetDepthInMainChain() == 0)
4366         {
4367             // if tx is expired, dont relay
4368             LogPrintf("Relaying wtx %s\n", GetHash().ToString());
4369             RelayTransaction((CTransaction)*this);
4370             return true;
4371         }
4372     }
4373     return false;
4374 }
4375
4376 set<uint256> CWalletTx::GetConflicts() const
4377 {
4378     set<uint256> result;
4379     if (pwallet != NULL)
4380     {
4381         uint256 myHash = GetHash();
4382         result = pwallet->GetConflicts(myHash);
4383         result.erase(myHash);
4384     }
4385     return result;
4386 }
4387
4388 CAmount CWalletTx::GetDebit(const isminefilter& filter) const
4389 {
4390     if (vin.empty())
4391         return 0;
4392
4393     CAmount debit = 0;
4394     if(filter & ISMINE_SPENDABLE)
4395     {
4396         if (fDebitCached)
4397             debit += nDebitCached;
4398         else
4399         {
4400             int depth = this->GetDepthInMainChain();
4401             uint32_t height = chainActive.Height() - --depth;
4402             nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE, height);
4403             fDebitCached = true;
4404             debit += nDebitCached;
4405         }
4406     }
4407     if(filter & ISMINE_WATCH_ONLY)
4408     {
4409         if(fWatchDebitCached)
4410             debit += nWatchDebitCached;
4411         else
4412         {
4413             int depth = this->GetDepthInMainChain();
4414             uint32_t height = chainActive.Height() - --depth;
4415             nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY, height);
4416             fWatchDebitCached = true;
4417             debit += nWatchDebitCached;
4418         }
4419     }
4420     return debit;
4421 }
4422
4423 CCurrencyValueMap CWalletTx::GetReserveDebit(const isminefilter& filter) const
4424 {
4425     if (vin.empty())
4426         return CCurrencyValueMap();
4427
4428     int depth = this->GetDepthInMainChain();
4429     uint32_t height = chainActive.Height() - --depth;
4430
4431     return pwallet->GetReserveDebit(*this, filter, height);
4432 }
4433
4434 CAmount CWalletTx::GetCredit(const isminefilter& filter) const
4435 {
4436     // Must wait until coinbase is safely deep enough in the chain before valuing it
4437     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4438         return 0;
4439
4440     int64_t credit = 0;
4441     if (filter & ISMINE_SPENDABLE)
4442     {
4443         // GetBalance can assume transactions in mapWallet won't change
4444         if (fCreditCached)
4445             credit += nCreditCached;
4446         else
4447         {
4448             int depth = this->GetDepthInMainChain();
4449             uint32_t height = chainActive.Height() - --depth;
4450
4451             nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE, height);
4452             fCreditCached = true;
4453             credit += nCreditCached;
4454         }
4455     }
4456     if (filter & ISMINE_WATCH_ONLY)
4457     {
4458         if (fWatchCreditCached)
4459             credit += nWatchCreditCached;
4460         else
4461         {
4462             int depth = this->GetDepthInMainChain();
4463             uint32_t height = chainActive.Height() - --depth;
4464
4465             nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY, height);
4466             fWatchCreditCached = true;
4467             credit += nWatchCreditCached;
4468         }
4469     }
4470     return credit;
4471 }
4472
4473 bool CWalletTx::HasMatureCoins() const
4474 {
4475     // Must wait until coinbase is safely deep enough in the chain before valuing it
4476     if (!(IsCoinBase() && GetBlocksToMaturity() > 0))
4477     {
4478         return true;
4479     }
4480     else
4481     {
4482         for (auto oneout : vout)
4483         {
4484             if (oneout.scriptPubKey.IsInstantSpend())
4485             {
4486                 return true;
4487             }
4488         }
4489         return false;
4490     }
4491 }
4492
4493 CCurrencyValueMap CWalletTx::GetReserveCredit(const isminefilter& filter) const
4494 {
4495     // Must wait until coinbase is safely deep enough in the chain before valuing it
4496     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4497         return CCurrencyValueMap();
4498
4499     return pwallet->GetReserveCredit(*this, filter);
4500 }
4501
4502 CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
4503 {
4504     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4505     {
4506         if (fUseCache && fImmatureCreditCached)
4507             return nImmatureCreditCached;
4508         nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
4509         fImmatureCreditCached = true;
4510         return nImmatureCreditCached;
4511     }
4512
4513     return 0;
4514 }
4515
4516 CCurrencyValueMap CWalletTx::GetImmatureReserveCredit(bool fUseCache) const
4517 {
4518     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4519     {
4520         pwallet->GetReserveCredit(*this, ISMINE_SPENDABLE);
4521     }
4522
4523     return CCurrencyValueMap();
4524 }
4525
4526 CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
4527 {
4528     if (pwallet == 0)
4529         return 0;
4530
4531     // Must wait until coinbase is safely deep enough in the chain before valuing it
4532     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4533         return 0;
4534
4535     if (fUseCache && fAvailableCreditCached)
4536         return nAvailableCreditCached;
4537
4538     CAmount nCredit = 0;
4539     uint256 hashTx = GetHash();
4540     for (unsigned int i = 0; i < vout.size(); i++)
4541     {
4542         if (!pwallet->IsSpent(hashTx, i) && vout[i].scriptPubKey.IsSpendableOutputType())
4543         {
4544             nCredit += pwallet->GetCredit(*this, i, ISMINE_SPENDABLE);
4545         }
4546     }
4547
4548     nAvailableCreditCached = nCredit;
4549     fAvailableCreditCached = true;
4550     return nCredit;
4551 }
4552
4553 CCurrencyValueMap CWalletTx::GetAvailableReserveCredit(bool fUseCache) const
4554 {
4555     CCurrencyValueMap retVal;
4556     if (pwallet == 0)
4557         return retVal;
4558
4559     // Must wait until coinbase is safely deep enough in the chain before valuing it
4560     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4561         return retVal;
4562
4563     uint256 hashTx = GetHash();
4564     for (unsigned int i = 0; i < vout.size(); i++)
4565     {
4566         if (!pwallet->IsSpent(hashTx, i) && vout[i].scriptPubKey.IsSpendableOutputType())
4567         {
4568             retVal += pwallet->GetReserveCredit(*this, i, ISMINE_SPENDABLE);
4569         }
4570     }
4571     return retVal;
4572 }
4573
4574 CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
4575 {
4576     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4577     {
4578         if (fUseCache && fImmatureWatchCreditCached)
4579             return nImmatureWatchCreditCached;
4580         nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
4581         fImmatureWatchCreditCached = true;
4582         return nImmatureWatchCreditCached;
4583     }
4584
4585     return 0;
4586 }
4587
4588 CCurrencyValueMap CWalletTx::GetImmatureWatchOnlyReserveCredit(const bool& fUseCache) const
4589 {
4590     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4591     {
4592        return pwallet->GetReserveCredit(*this, ISMINE_WATCH_ONLY);
4593     }
4594
4595     return CCurrencyValueMap();
4596 }
4597
4598 CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
4599 {
4600     if (pwallet == 0)
4601         return 0;
4602
4603     // Must wait until coinbase is safely deep enough in the chain before valuing it
4604     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4605         return 0;
4606
4607     if (fUseCache && fAvailableWatchCreditCached)
4608         return nAvailableWatchCreditCached;
4609
4610     CAmount nCredit = 0;
4611     for (unsigned int i = 0; i < vout.size(); i++)
4612     {
4613         if (!pwallet->IsSpent(GetHash(), i))
4614         {
4615             nCredit += pwallet->GetCredit(*this, i, ISMINE_WATCH_ONLY);
4616             if (!MoneyRange(nCredit))
4617                 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
4618         }
4619     }
4620
4621     nAvailableWatchCreditCached = nCredit;
4622     fAvailableWatchCreditCached = true;
4623     return nCredit;
4624 }
4625
4626 CCurrencyValueMap CWalletTx::GetAvailableWatchOnlyReserveCredit(const bool& fUseCache) const
4627 {
4628     CCurrencyValueMap retVal;
4629     if (pwallet == 0)
4630         return retVal;
4631
4632     // Must wait until coinbase is safely deep enough in the chain before valuing it
4633     if (IsCoinBase() && GetBlocksToMaturity() > 0)
4634         return retVal;
4635
4636     for (unsigned int i = 0; i < vout.size(); i++)
4637     {
4638         if (!pwallet->IsSpent(GetHash(), i))
4639         {
4640             retVal += pwallet->GetReserveCredit(*this, i, ISMINE_WATCH_ONLY);
4641         }
4642     }
4643
4644     return retVal;
4645 }
4646
4647 CAmount CWalletTx::GetChange() const
4648 {
4649     if (fChangeCached)
4650         return nChangeCached;
4651     nChangeCached = pwallet->GetChange(*this);
4652     fChangeCached = true;
4653     return nChangeCached;
4654 }
4655
4656 bool CWalletTx::IsTrusted() const
4657 {
4658     // Quick answer in most cases
4659     if (!CheckFinalTx(*this))
4660         return false;
4661     int nDepth = GetDepthInMainChain();
4662     if (nDepth >= 1)
4663         return true;
4664     if (nDepth < 0)
4665         return false;
4666     if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
4667         return false;
4668
4669     // Trusted if all inputs are from us and are in the mempool:
4670     BOOST_FOREACH(const CTxIn& txin, vin)
4671     {
4672         // Transactions not sent by us: not trusted
4673         const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
4674         if (parent == NULL)
4675             return false;
4676         if (!parent->vout.size())
4677         {
4678             LogPrintf("%s: No spendable output in wallet for input to %s, num %d\n", __func__, txin.prevout.hash.GetHex().c_str(), txin.prevout.n);
4679             return false;
4680         }
4681         const CTxOut& parentOut = parent->vout[txin.prevout.n];
4682         if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
4683             return false;
4684     }
4685     return true;
4686 }
4687
4688 std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
4689 {
4690     std::vector<uint256> result;
4691
4692     LOCK(cs_wallet);
4693     // Sort them in chronological order
4694     multimap<unsigned int, CWalletTx*> mapSorted;
4695     uint32_t now = (uint32_t)time(NULL);
4696     std::vector<uint256> vwtxh;
4697     BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
4698     {
4699         CWalletTx& wtx = item.second;
4700         // Don't rebroadcast if newer than nTime:
4701         if (wtx.nTimeReceived > nTime)
4702             continue;
4703         if ( (wtx.nLockTime >= LOCKTIME_THRESHOLD && wtx.nLockTime < now-KOMODO_MAXMEMPOOLTIME) || wtx.hashBlock.IsNull() )
4704         {
4705             //LogPrintf("skip Relaying wtx %s nLockTime %u vs now.%u\n", wtx.GetHash().ToString(),(uint32_t)wtx.nLockTime,now);
4706             //vwtxh.push_back(wtx.GetHash());
4707             continue;
4708         }
4709         mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
4710     }
4711     BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
4712     {
4713         if ( item.second != 0 )
4714         {
4715             CWalletTx &wtx = *item.second;
4716             if (wtx.RelayWalletTransaction())
4717                 result.push_back(wtx.GetHash());
4718         }
4719     }
4720     for (auto hash : vwtxh)
4721     {
4722         EraseFromWallets(hash);
4723     }
4724     return result;
4725 }
4726
4727 void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
4728 {
4729     // Do this infrequently and randomly to avoid giving away
4730     // that these are our transactions.
4731     if (GetTime() < nNextResend || !fBroadcastTransactions)
4732         return;
4733     bool fFirst = (nNextResend == 0);
4734     nNextResend = GetTime() + GetRand(30 * 60);
4735     if (fFirst)
4736         return;
4737
4738     // Only do it if there's been a new block since last time
4739     if (nBestBlockTime < nLastResend)
4740         return;
4741     nLastResend = GetTime();
4742
4743     // Rebroadcast unconfirmed txes older than 5 minutes before the last
4744     // block was found:
4745     std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60);
4746     if (!relayed.empty())
4747         LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
4748 }
4749
4750 /** @} */ // end of mapWallet
4751
4752
4753
4754
4755 /** @defgroup Actions
4756  *
4757  * @{
4758  */
4759
4760
4761 CAmount CWallet::GetBalance() const
4762 {
4763     CAmount nTotal = 0;
4764     {
4765         LOCK2(cs_main, cs_wallet);
4766         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4767         {
4768             const CWalletTx* pcoin = &(*it).second;
4769             if (pcoin->IsTrusted())
4770                 nTotal += pcoin->GetAvailableCredit();
4771         }
4772     }
4773
4774     return nTotal;
4775 }
4776
4777 CCurrencyValueMap CWallet::GetReserveBalance() const
4778 {
4779     CCurrencyValueMap retVal;
4780     {
4781         LOCK2(cs_main, cs_wallet);
4782         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4783         {
4784             const CWalletTx* pcoin = &(*it).second;
4785             if (pcoin->IsTrusted())
4786                 retVal += pcoin->GetAvailableReserveCredit();
4787         }
4788     }
4789
4790     return retVal;
4791 }
4792
4793 CAmount CWallet::GetUnconfirmedBalance() const
4794 {
4795     CAmount nTotal = 0;
4796     {
4797         LOCK2(cs_main, cs_wallet);
4798         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4799         {
4800             const CWalletTx* pcoin = &(*it).second;
4801             if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4802                 nTotal += pcoin->GetAvailableCredit();
4803         }
4804     }
4805     return nTotal;
4806 }
4807
4808 CCurrencyValueMap CWallet::GetUnconfirmedReserveBalance() const
4809 {
4810     CCurrencyValueMap retVal;
4811     {
4812         LOCK2(cs_main, cs_wallet);
4813         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4814         {
4815             const CWalletTx* pcoin = &(*it).second;
4816             if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4817                 retVal += pcoin->GetAvailableReserveCredit();
4818         }
4819     }
4820     return retVal;
4821 }
4822
4823 CAmount CWallet::GetImmatureBalance() const
4824 {
4825     CAmount nTotal = 0;
4826     {
4827         LOCK2(cs_main, cs_wallet);
4828         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4829         {
4830             const CWalletTx* pcoin = &(*it).second;
4831             nTotal += pcoin->GetImmatureCredit();
4832         }
4833     }
4834     return nTotal;
4835 }
4836
4837 CCurrencyValueMap CWallet::GetImmatureReserveBalance() const
4838 {
4839     CCurrencyValueMap retVal;
4840     {
4841         LOCK2(cs_main, cs_wallet);
4842         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4843         {
4844             const CWalletTx* pcoin = &(*it).second;
4845             retVal += pcoin->GetImmatureReserveCredit();
4846         }
4847     }
4848     return retVal;
4849 }
4850
4851 CAmount CWallet::GetWatchOnlyBalance() const
4852 {
4853     CAmount nTotal = 0;
4854     {
4855         LOCK2(cs_main, cs_wallet);
4856         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4857         {
4858             const CWalletTx* pcoin = &(*it).second;
4859             if (pcoin->IsTrusted())
4860                 nTotal += pcoin->GetAvailableWatchOnlyCredit();
4861         }
4862     }
4863
4864     return nTotal;
4865 }
4866
4867 CCurrencyValueMap CWallet::GetWatchOnlyReserveBalance() const
4868 {
4869     CCurrencyValueMap retVal;
4870     {
4871         LOCK2(cs_main, cs_wallet);
4872         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4873         {
4874             const CWalletTx* pcoin = &(*it).second;
4875             if (pcoin->IsTrusted())
4876                 retVal += pcoin->GetAvailableWatchOnlyReserveCredit();
4877         }
4878     }
4879
4880     return retVal;
4881 }
4882
4883 CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
4884 {
4885     CAmount nTotal = 0;
4886     {
4887         LOCK2(cs_main, cs_wallet);
4888         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4889         {
4890             const CWalletTx* pcoin = &(*it).second;
4891             if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4892                 nTotal += pcoin->GetAvailableWatchOnlyCredit();
4893         }
4894     }
4895     return nTotal;
4896 }
4897
4898 CCurrencyValueMap CWallet::GetUnconfirmedWatchOnlyReserveBalance() const
4899 {
4900     CCurrencyValueMap retVal;
4901     {
4902         LOCK2(cs_main, cs_wallet);
4903         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4904         {
4905             const CWalletTx* pcoin = &(*it).second;
4906             if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4907                 retVal += pcoin->GetAvailableWatchOnlyReserveCredit();
4908         }
4909     }
4910     return retVal;
4911 }
4912
4913 CAmount CWallet::GetImmatureWatchOnlyBalance() const
4914 {
4915     CAmount nTotal = 0;
4916     {
4917         LOCK2(cs_main, cs_wallet);
4918         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4919         {
4920             const CWalletTx* pcoin = &(*it).second;
4921             nTotal += pcoin->GetImmatureWatchOnlyCredit();
4922         }
4923     }
4924     return nTotal;
4925 }
4926
4927 CCurrencyValueMap CWallet::GetImmatureWatchOnlyReserveBalance() const
4928 {
4929     CCurrencyValueMap retVal;
4930     {
4931         LOCK2(cs_main, cs_wallet);
4932         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4933         {
4934             const CWalletTx* pcoin = &(*it).second;
4935             retVal += pcoin->GetImmatureWatchOnlyReserveCredit();
4936         }
4937     }
4938     return retVal;
4939 }
4940
4941 /**
4942  * populate vCoins with vector of available COutputs.
4943  */
4944 uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
4945 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
4946
4947 void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase, bool fIncludeProtectedCoinbase, bool fIncludeImmatureCoins) const
4948 {
4949     uint64_t interest,*ptr;
4950     vCoins.clear();
4951
4952     {
4953         LOCK2(cs_main, cs_wallet);
4954         uint32_t nHeight = chainActive.Height() + 1;
4955         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4956         {
4957             const uint256& wtxid = it->first;
4958             const CWalletTx* pcoin = &(*it).second;
4959
4960             if (!CheckFinalTx(*pcoin))
4961                 continue;
4962
4963             if (fOnlyConfirmed && !pcoin->IsTrusted())
4964                 continue;
4965
4966             bool isCoinbase = pcoin->IsCoinBase();
4967             if (!fIncludeCoinBase && isCoinbase)
4968                 continue;
4969             
4970             if (!fIncludeImmatureCoins && isCoinbase && pcoin->GetBlocksToMaturity() > 0)
4971                 continue;
4972
4973             int nDepth = pcoin->GetDepthInMainChain();
4974             if (nDepth < 0)
4975                 continue;
4976  
4977             uint32_t coinHeight = nHeight - nDepth;
4978             // even if we should include coinbases, we may opt to exclude protected coinbases, which must only be included when shielding
4979             if (isCoinbase && 
4980                 !fIncludeProtectedCoinbase && 
4981                 Params().GetConsensus().fCoinbaseMustBeProtected && 
4982                 CConstVerusSolutionVector::GetVersionByHeight(coinHeight) < CActivationHeight::SOLUTION_VERUSV4 &&
4983                 CConstVerusSolutionVector::GetVersionByHeight(nHeight) < CActivationHeight::SOLUTION_VERUSV5)
4984                 continue;
4985
4986             for (int i = 0; i < pcoin->vout.size(); i++)
4987             {
4988                 isminetype mine = IsMine(pcoin->vout[i]);
4989                 if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
4990                     !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) &&
4991                     (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
4992                 {
4993                     if ( KOMODO_EXCHANGEWALLET == 0 )
4994                     {
4995                         uint32_t locktime; int32_t txheight; CBlockIndex *tipindex;
4996                         if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->GetHeight() >= 60000 )
4997                         {
4998                             if ( pcoin->vout[i].nValue >= 10*COIN )
4999                             {
5000                                 if ( (tipindex= chainActive.LastTip()) != 0 )
5001                                 {
5002                                     komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue,(int32_t)tipindex->GetHeight());
5003                                     interest = komodo_interestnew(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime);
5004                                 } else interest = 0;
5005                                 //interest = komodo_interestnew(chainActive.LastTip()->GetHeight()+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.LastTip()->nTime);
5006                                 if ( interest != 0 )
5007                                 {
5008                                     //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);
5009                                     //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.LastTip()->GetHeight()+1,pcoin->nLockTime,chainActive.LastTip()->nTime);
5010                                     //ptr = (uint64_t *)&pcoin->vout[i].nValue;
5011                                     //(*ptr) += interest;
5012                                     ptr = (uint64_t *)&pcoin->vout[i].interest;
5013                                     (*ptr) = interest;
5014                                     //pcoin->vout[i].nValue += interest;
5015                                 }
5016                                 else
5017                                 {
5018                                     ptr = (uint64_t *)&pcoin->vout[i].interest;
5019                                     (*ptr) = 0;
5020                                 }
5021                             }
5022                             else
5023                             {
5024                                 ptr = (uint64_t *)&pcoin->vout[i].interest;
5025                                 (*ptr) = 0;
5026                             }
5027                         }
5028                         else
5029                         {
5030                             ptr = (uint64_t *)&pcoin->vout[i].interest;
5031                             (*ptr) = 0;
5032                         }
5033                     }
5034                     vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
5035                 }
5036             }
5037         }
5038     }
5039 }
5040
5041 void CWallet::AvailableReserveCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeCoinBase, bool fIncludeNative, const CTxDestination *pOnlyFromDest, const CCurrencyValueMap *pOnlyTheseCurrencies) const
5042 {
5043     vCoins.clear();
5044
5045     {
5046         LOCK2(cs_main, cs_wallet);
5047         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
5048         {
5049             const uint256& wtxid = it->first;
5050             const CWalletTx* pcoin = &(*it).second;
5051
5052             if (!CheckFinalTx(*pcoin))
5053                 continue;
5054
5055             if (fOnlyConfirmed && !pcoin->IsTrusted())
5056                 continue;
5057
5058             if (pcoin->IsCoinBase() && !fIncludeCoinBase)
5059                 continue;
5060
5061             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
5062                 continue;
5063
5064             int nDepth = pcoin->GetDepthInMainChain();
5065             if (nDepth < 0)
5066                 continue;
5067  
5068             for (int i = 0; i < pcoin->vout.size(); i++)
5069             {
5070                 isminetype mine = IsMine(pcoin->vout[i]);
5071                 if (!(IsSpent(wtxid, i)) &&
5072                     mine != ISMINE_NO &&
5073                     !IsLockedCoin((*it).first, i) &&
5074                     (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
5075                 {
5076                     COptCCParams p;
5077                     CCurrencyValueMap rOut = pcoin->vout[i].scriptPubKey.ReserveOutValue(p, true);
5078
5079                     if (p.IsValid() && !pcoin->vout[i].scriptPubKey.IsSpendableOutputType(p))
5080                     {
5081                         continue;
5082                     }
5083                     if (pOnlyFromDest)
5084                     {
5085                         if (p.IsValid())
5086                         {
5087                             bool found = false;
5088                             for (auto &oneDest : p.vKeys)
5089                             {
5090                                 if (GetDestinationID(oneDest) == GetDestinationID(*pOnlyFromDest))
5091                                 {
5092                                     found = true;
5093                                     break;
5094                                 }
5095                             }
5096                             if (!found)
5097                             {
5098                                 continue;
5099                             }
5100                         }
5101                         else
5102                         {
5103                             // support P2PK or P2PKH
5104                             CTxDestination dest;
5105                             if (!ExtractDestination(pcoin->vout[i].scriptPubKey, dest) || GetDestinationID(dest) != GetDestinationID(*pOnlyFromDest))
5106                             {
5107                                 continue;
5108                             }
5109                         }
5110                     }
5111                     // don't return zero valued outputs
5112                     if (rOut.CanonicalMap().valueMap.size() || pcoin->vout[i].nValue)
5113                     {
5114                         if ((rOut.valueMap.size() && (!pOnlyTheseCurrencies || (pOnlyTheseCurrencies && pOnlyTheseCurrencies->Intersects(rOut)))) || 
5115                             (fIncludeNative && pcoin->vout[i].nValue))
5116                         {
5117                             vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
5118                         }
5119                     }
5120                 }
5121             }
5122         }
5123     }
5124 }
5125
5126 bool CWallet::GetAndValidateSaplingZAddress(const std::string &addressStr, libzcash::PaymentAddress &zaddress)
5127 {
5128     std::string addrCopy = addressStr;
5129     std::vector<std::string> addressParts;
5130     boost::split(addressParts, addrCopy, boost::is_any_of(":"));
5131
5132     if (addressParts.size() == 2 && addressParts[1] == "private")
5133     {
5134         // look up to see if this is the private address of an ID. if not, or if the ID does not have a valid, Sapling address, it is invalid
5135         CTxDestination destination = DecodeDestination(addressParts[0]);
5136         if (destination.which() == COptCCParams::ADDRTYPE_ID)
5137         {
5138             AssertLockHeld(cs_main);
5139             CIdentity idSource = CIdentity::LookupIdentity(GetDestinationID(destination));
5140             if (idSource.IsValid() && idSource.privateAddresses.size() > 0)
5141             {
5142                 zaddress = idSource.privateAddresses[0];
5143                 return true;
5144             }
5145         }
5146         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid ID or ID that does not have valid z-address specified");
5147     }
5148
5149     zaddress = DecodePaymentAddress(addrCopy);
5150     bool hasZSource = boost::get<libzcash::SaplingPaymentAddress>(&zaddress) != nullptr;
5151     if (!hasZSource && boost::get<libzcash::SproutPaymentAddress>(&zaddress) != nullptr)
5152     {
5153         throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy Sprout address not supported. Use a transparent or Sapling compatible address");
5154     }
5155     return hasZSource;
5156 }
5157
5158 static 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)
5159 {
5160     vector<char> vfIncluded;
5161
5162     vfBest.assign(vValue.size(), true);
5163     nBest = nTotalLower;
5164
5165     seed_insecure_rand();
5166
5167     for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
5168     {
5169         vfIncluded.assign(vValue.size(), false);
5170         CAmount nTotal = 0;
5171         bool fReachedTarget = false;
5172         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
5173         {
5174             for (unsigned int i = 0; i < vValue.size(); i++)
5175             {
5176                 //The solver here uses a randomized algorithm,
5177                 //the randomness serves no real security purpose but is just
5178                 //needed to prevent degenerate behavior and it is important
5179                 //that the rng is fast. We do not use a constant random sequence,
5180                 //because there may be some privacy improvement by making
5181                 //the selection random.
5182                 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
5183                 {
5184                     nTotal += vValue[i].first;
5185                     vfIncluded[i] = true;
5186                     if (nTotal >= nTargetValue)
5187                     {
5188                         fReachedTarget = true;
5189                         if (nTotal < nBest)
5190                         {
5191                             nBest = nTotal;
5192                             vfBest = vfIncluded;
5193                         }
5194                         nTotal -= vValue[i].first;
5195                         vfIncluded[i] = false;
5196                     }
5197                 }
5198             }
5199         }
5200     }
5201 }
5202
5203 // returns true if the selection contributes to getting any closer to the target. for example,
5204 // if a candidate value map contains more of currencies already present and none of those that are needed
5205 // but not present, it will return false. if it contains currencies that are needed, it will return
5206 // true.
5207 bool CloserToTarget(const CCurrencyValueMap &target, const CCurrencyValueMap &current, const CCurrencyValueMap &candidate)
5208 {
5209     CCurrencyValueMap workingTarget = target.SubtractToZero(current);   // whatever is left is what we still need
5210     return workingTarget.SubtractToZero(candidate) < workingTarget;
5211 }
5212
5213 static void ApproximateBestReserveSubset(vector<pair<CCurrencyValueMap, pair<const CWalletTx*,unsigned int> > >vValue, 
5214                                          const CCurrencyValueMap &totalToOptimize, 
5215                                          const CCurrencyValueMap &targetValues,
5216                                          vector<char>& vfBest, 
5217                                          CCurrencyValueMap& bestTotals, 
5218                                          int iterations = 1000)
5219 {
5220     vector<char> vfIncluded;
5221
5222     vfBest.assign(vValue.size(), true);
5223     bestTotals = totalToOptimize;
5224
5225     seed_insecure_rand();
5226
5227     for (int nRep = 0; nRep < iterations && bestTotals != targetValues; nRep++)
5228     {
5229         vfIncluded.assign(vValue.size(), false);
5230         CCurrencyValueMap totals;
5231         std::set<uint160> satisfied;
5232         bool fReachedTarget = false;
5233         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
5234         {
5235             CCurrencyValueMap adjustedTarget(targetValues);
5236             CCurrencyValueMap presentValues;
5237             for (unsigned int i = 0; i < vValue.size(); i++)
5238             {
5239                 //The solver here uses a randomized algorithm,
5240                 //the randomness serves no real security purpose but is just
5241                 //needed to prevent degenerate behavior and it is important
5242                 //that the rng is fast. We do not use a constant random sequence,
5243                 //because there may be some privacy improvement by making
5244                 //the selection random.
5245                 /*
5246                 printf("targetValues\n%s\ntotals\n%s\nvValue[i].first\n%s\n", targetValues.ToUniValue().write(1,2).c_str(), 
5247                                                                               totals.ToUniValue().write(1,2).c_str(), 
5248                                                                               vValue[i].first.ToUniValue().write(1,2).c_str());
5249                 printf("iscloser: %d\n", CloserToTarget(targetValues, totals, vValue[i].first));
5250                 */
5251
5252                 if ((nPass == 0 ? insecure_rand()&1 : !vfIncluded[i]) && CloserToTarget(targetValues, totals, vValue[i].first))
5253                 {
5254                     totals += vValue[i].first.IntersectingValues(targetValues);
5255                     vfIncluded[i] = true;
5256                     // we reached the target if we fulfill all currencies
5257
5258                     adjustedTarget = targetValues.SubtractToZero(totals);
5259
5260                     // loop through all those that have been zeroed in the adjusted target, and mark as satisfied
5261                     for (auto &oneCur : targetValues.NonIntersectingValues(adjustedTarget).valueMap)
5262                     {
5263                         satisfied.insert(oneCur.first);
5264                     }
5265
5266                     if (satisfied.size() == targetValues.valueMap.size())
5267                     {
5268                         fReachedTarget = true;
5269                         CompareValueMap comparator(targetValues);
5270                         if (comparator.CompareMaps(totals, bestTotals))
5271                         {
5272                             bestTotals = totals;
5273                             vfBest = vfIncluded;
5274                         }
5275                         totals -= vValue[i].first;
5276                         vfIncluded[i] = false;
5277                     }
5278                 }
5279             }
5280         }
5281     }
5282 }
5283
5284 bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
5285 {
5286     int32_t count = 0; //uint64_t lowest_interest = 0;
5287     setCoinsRet.clear();
5288     //memset(interests,0,sizeof(interests));
5289     nValueRet = 0;
5290     // List of values less than target
5291     pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
5292     coinLowestLarger.first = std::numeric_limits<CAmount>::max();
5293     coinLowestLarger.second.first = NULL;
5294     vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue;
5295     CAmount nTotalLower = 0;
5296
5297     random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
5298
5299     BOOST_FOREACH(const COutput &output, vCoins)
5300     {
5301         if (!output.fSpendable)
5302             continue;
5303
5304         if (output.tx->vout[output.i].nValue == 0)
5305         {
5306             continue;
5307         }
5308
5309         const CWalletTx *pcoin = output.tx;
5310
5311         if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
5312             continue;
5313
5314         int i = output.i;
5315         CAmount n = pcoin->vout[i].nValue;
5316
5317         pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
5318
5319         if (n == nTargetValue)
5320         {
5321             setCoinsRet.insert(coin.second);
5322             nValueRet += coin.first;
5323             //if ( KOMODO_EXCHANGEWALLET == 0 )
5324             //    *interestp += pcoin->vout[i].interest;
5325             return true;
5326         }
5327         else if (n < nTargetValue + CENT)
5328         {
5329             vValue.push_back(coin);
5330             nTotalLower += n;
5331             //if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) )
5332             //{
5333                 //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN);
5334                 //interests[count++] = pcoin->vout[i].interest;
5335             //}
5336             if ( nTotalLower > 4*nTargetValue + CENT )
5337             {
5338                 //fprintf(stderr,"why bother with all the utxo if we have double what is needed?\n");
5339                 break;
5340             }
5341         }
5342         else if (n < coinLowestLarger.first)
5343         {
5344             coinLowestLarger = coin;
5345             //if ( KOMODO_EXCHANGEWALLET == 0 )
5346             //    lowest_interest = pcoin->vout[i].interest;
5347         }
5348     }
5349
5350     if (nTotalLower == nTargetValue)
5351     {
5352         for (unsigned int i = 0; i < vValue.size(); ++i)
5353         {
5354             setCoinsRet.insert(vValue[i].second);
5355             nValueRet += vValue[i].first;
5356             //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
5357             //    *interestp += interests[i];
5358         }
5359         return true;
5360     }
5361
5362     if (nTotalLower < nTargetValue)
5363     {
5364         if (coinLowestLarger.second.first == NULL)
5365             return false;
5366         setCoinsRet.insert(coinLowestLarger.second);
5367         nValueRet += coinLowestLarger.first;
5368         //if ( KOMODO_EXCHANGEWALLET == 0 )
5369         //    *interestp += lowest_interest;
5370         return true;
5371     }
5372
5373     // Solve subset sum by stochastic approximation
5374     sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
5375     vector<char> vfBest;
5376     CAmount nBest;
5377
5378     ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
5379     if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
5380         ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
5381
5382     // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
5383     //                                   or the next bigger coin is closer), return the bigger coin
5384     if (coinLowestLarger.second.first &&
5385         ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
5386     {
5387         setCoinsRet.insert(coinLowestLarger.second);
5388         nValueRet += coinLowestLarger.first;
5389         //if ( KOMODO_EXCHANGEWALLET == 0 )
5390         //    *interestp += lowest_interest;
5391     }
5392     else {
5393         for (unsigned int i = 0; i < vValue.size(); i++)
5394             if (vfBest[i])
5395             {
5396                 setCoinsRet.insert(vValue[i].second);
5397                 nValueRet += vValue[i].first;
5398                 //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
5399                 //    *interestp += interests[i];
5400             }
5401
5402         LogPrint("selectcoins", "SelectCoins() best subset: ");
5403         for (unsigned int i = 0; i < vValue.size(); i++)
5404             if (vfBest[i])
5405                 LogPrint("selectcoins", "%s", FormatMoney(vValue[i].first));
5406         LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
5407     }
5408
5409     return true;
5410 }
5411
5412 bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet,  bool& fOnlyProtectedCoinbaseCoinsRet, bool& fNeedProtectedCoinbaseCoinsRet, const CCoinControl* coinControl) const
5413 {
5414     // Output parameter fOnlyProtectedCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
5415     uint64_t tmp; int32_t retval;
5416     //if ( interestp == 0 )
5417     //{
5418     //    interestp = &tmp;
5419     //    *interestp = 0;
5420     //}
5421     vector<COutput> vCoinsNoCoinbase, vCoinsWithCoinbase;
5422     AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, true, false);
5423     AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true, true);
5424     fOnlyProtectedCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
5425
5426     // If coinbase utxos can only be sent to zaddrs, exclude any coinbase utxos from coin selection.
5427     bool fProtectCoinbase = Params().GetConsensus().fCoinbaseMustBeProtected;
5428     vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
5429
5430     // Output parameter fNeedProtectedCoinbaseCoinsRet is set to true if coinbase utxos that must be shielded need to be spent to meet target amount
5431     if (fProtectCoinbase && vCoinsWithCoinbase.size() > vCoinsNoCoinbase.size()) {
5432         CAmount value = 0;
5433         for (const COutput& out : vCoinsNoCoinbase) {
5434             if (!out.fSpendable) {
5435                 continue;
5436             }
5437             value += out.tx->vout[out.i].nValue;
5438             if ( KOMODO_EXCHANGEWALLET == 0 )
5439                 value += out.tx->vout[out.i].interest;
5440         }
5441         if (value <= nTargetValue) {
5442             CAmount valueWithCoinbase = 0;
5443             for (const COutput& out : vCoinsWithCoinbase) {
5444                 if (!out.fSpendable) {
5445                     continue;
5446                 }
5447                 valueWithCoinbase += out.tx->vout[out.i].nValue;
5448                 if ( KOMODO_EXCHANGEWALLET == 0 )
5449                     valueWithCoinbase += out.tx->vout[out.i].interest;
5450             }
5451             fNeedProtectedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
5452         }
5453     }
5454     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
5455     if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
5456     {
5457         BOOST_FOREACH(const COutput& out, vCoins)
5458         {
5459             if (!out.fSpendable)
5460                  continue;
5461             nValueRet += out.tx->vout[out.i].nValue;
5462             //if ( KOMODO_EXCHANGEWALLET == 0 )
5463             //    *interestp += out.tx->vout[out.i].interest;
5464             setCoinsRet.insert(make_pair(out.tx, out.i));
5465         }
5466         return (nValueRet >= nTargetValue);
5467     }
5468     // calculate value from preset inputs and store them
5469     set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
5470     CAmount nValueFromPresetInputs = 0;
5471
5472     std::vector<COutPoint> vPresetInputs;
5473     if (coinControl)
5474         coinControl->ListSelected(vPresetInputs);
5475     BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
5476     {
5477         map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
5478         if (it != mapWallet.end())
5479         {
5480             const CWalletTx* pcoin = &it->second;
5481             // Clearly invalid input, fail
5482             if (pcoin->vout.size() <= outpoint.n)
5483                 return false;
5484             nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue;
5485             if ( KOMODO_EXCHANGEWALLET == 0 )
5486                 nValueFromPresetInputs += pcoin->vout[outpoint.n].interest;
5487             setPresetCoins.insert(make_pair(pcoin, outpoint.n));
5488         } else
5489             return false; // TODO: Allow non-wallet inputs
5490     }
5491
5492     // remove preset inputs from vCoins
5493     for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
5494     {
5495         if (setPresetCoins.count(make_pair(it->tx, it->i)))
5496             it = vCoins.erase(it);
5497         else
5498             ++it;
5499     }
5500     retval = false;
5501     if ( nTargetValue <= nValueFromPresetInputs )
5502         retval = true;
5503     else if ( SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) != 0 )
5504         retval = true;
5505     else if ( SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) != 0 )
5506         retval = true;
5507     else if ( bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet) != 0 )
5508         retval = true;
5509     // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
5510     setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
5511     // add preset inputs to the total value selected
5512     nValueRet += nValueFromPresetInputs;
5513     return retval;
5514 }
5515
5516 bool CWallet::SelectReserveCoinsMinConf(const CCurrencyValueMap& targetValues, 
5517                                         CAmount targetNativeValue, 
5518                                         int nConfMine, 
5519                                         int nConfTheirs, 
5520                                         std::vector<COutput> vCoins, 
5521                                         std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, 
5522                                         CCurrencyValueMap& valueRet,
5523                                         CAmount &nativeValueRet) const
5524 {
5525     int32_t count = 0; //uint64_t lowest_interest = 0;
5526     setCoinsRet.clear();
5527     valueRet.valueMap.clear();
5528     nativeValueRet = 0;
5529     //memset(interests,0,sizeof(interests));
5530
5531     // for each currency type being looked for, store the lowest larger outputs found in order, up to a maximum of the number of
5532     // different currencies being looked for
5533     std::map<uint160, std::multimap<CAmount, CReserveOutSelectionInfo>> coinsLowestLarger;
5534     std::map<std::pair<const CWalletTx *, int>, CCurrencyValueMap> largerOuts;       // all those that are >= than amount requested in at least one currency
5535     std::multimap<int, std::pair<std::vector<uint160>, CReserveOutSelectionInfo>> multiSatisfy;  // for outputs that satisfy >= one currency
5536     CCurrencyValueMap largerTotal;
5537     std::map<uint160, std::multimap<CAmount, CReserveOutSelectionInfo>> coinsLargestLower;
5538     std::map<std::pair<const CWalletTx *, int>, CCurrencyValueMap> lowerOuts;        // all those that are lower or unneeded for larger and helpful
5539     CCurrencyValueMap lowerTotal;
5540
5541     CCurrencyValueMap nativeCent(std::vector<uint160>({ASSETCHAINS_CHAINID}), std::vector<CAmount>({CENT}));
5542
5543     CCurrencyValueMap totalToOptimize;
5544     std::vector<std::pair<CCurrencyValueMap, std::pair<const CWalletTx*, unsigned int>>> vOutputsToOptimize;
5545
5546     random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
5547
5548     CCurrencyValueMap nTotalTarget = (targetValues + CCurrencyValueMap(std::vector<uint160>({ASSETCHAINS_CHAINID}), std::vector<CAmount>({targetNativeValue}))).CanonicalMap();
5549
5550     //printf("totaltarget: %s\n", nTotalTarget.ToUniValue().write().c_str());
5551
5552     // currencies in the target that are satisfied x4 in the lower list
5553     std::set<uint160> satisfied_x4;
5554     CCurrencyValueMap targetx4(nTotalTarget * 4 + nativeCent);
5555
5556     for (const COutput &output : vCoins)
5557     {
5558         if (!output.fSpendable)
5559             continue;
5560
5561         const CWalletTx *pcoin = output.tx;
5562
5563         if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
5564             continue;
5565
5566         int i = output.i;
5567         CCurrencyValueMap nAll(pcoin->vout[i].scriptPubKey.ReserveOutValue());  // all currencies, whether in target or not
5568         CCurrencyValueMap nTotal = nAll.IntersectingValues(targetValues); // nTotal will be all currencies, including native, that are also in target
5569         CAmount nativeN = pcoin->vout[i].nValue;
5570         if (nativeN)
5571         {
5572             nAll.valueMap[ASSETCHAINS_CHAINID] = nativeN;
5573             if (targetNativeValue)
5574             {
5575                 nTotal.valueMap[ASSETCHAINS_CHAINID] = nativeN;
5576             }
5577         }
5578
5579         // if it has no output types we care about, next
5580         if (!nTotal.valueMap.size())
5581         {
5582             continue;
5583         }
5584
5585         //printf("nTotal: %s\n", nTotal.ToUniValue().write().c_str());
5586
5587         CReserveOutSelectionInfo coin(pcoin, i, nAll);
5588
5589         // if all values are equivalent to targets, we've found the perfect output, no more searching needed
5590         // TODO: should we early out, even if we have extra currencies? If so, use nTotal to commpare
5591         if (nTotal == nTotalTarget)
5592         {
5593             setCoinsRet.insert(std::make_pair(coin.pWtx, coin.n));
5594             valueRet = pcoin->vout[i].scriptPubKey.ReserveOutValue();
5595             nativeValueRet = nativeN;
5596             return true;
5597         }
5598
5599         CCurrencyValueMap subtractedFromTarget(nTotalTarget.SubtractToZero(nTotal));
5600
5601         // now, we need to loop through all targets to see if this satisfies any single currency requirement completely
5602         // if so, we will include it in the largest lower list for that currency
5603         int numLarger = 0;
5604         std::vector<uint160> multiCurrencies;
5605
5606         COutput sanitizedOutput(output.tx, output.i, 0, true);
5607
5608         // if we have some entries larger than target
5609         if (subtractedFromTarget.valueMap.size() < nTotalTarget.valueMap.size())
5610         {
5611             //printf("subtractedFromTarget:\n%s\nnTotalTarget:\n%s\nnTotal.NonIntersectingValues(subtractedFromTarget):\n%s\n", subtractedFromTarget.ToUniValue().write().c_str(), nTotal.ToUniValue().write().c_str(), nTotalTarget.NonIntersectingValues(subtractedFromTarget).ToUniValue().write().c_str());
5612             for (auto oneCur : nTotal.NonIntersectingValues(subtractedFromTarget).valueMap)
5613             {
5614                 coinsLowestLarger[oneCur.first].insert(std::make_pair(oneCur.second, CReserveOutSelectionInfo(output.tx, output.i, nAll)));
5615                 multiCurrencies.push_back(oneCur.first);
5616                 numLarger++;
5617             }
5618         }
5619         if (numLarger)
5620         {
5621             largerOuts.insert(std::make_pair(std::make_pair(output.tx, output.i), nAll));
5622             largerTotal += nTotal;
5623             multiSatisfy.insert(std::make_pair(numLarger, std::make_pair(multiCurrencies, coin)));
5624         }
5625         else
5626         {
5627             bool neededCurrency = false;
5628             for (auto &oneCur : nTotal.valueMap)
5629             {
5630                 if (satisfied_x4.count(oneCur.first))
5631                 {
5632                     continue;
5633                 }
5634                 neededCurrency = true;
5635                 coinsLargestLower[oneCur.first].insert(std::make_pair(oneCur.second, coin));
5636             }
5637             if (!neededCurrency)
5638             {
5639                 continue;
5640             }
5641
5642             lowerOuts.insert(std::make_pair(std::make_pair(output.tx, output.i), nAll));
5643             lowerTotal += nTotal;
5644
5645             CCurrencyValueMap adjTargetx4 = targetx4.SubtractToZero(lowerTotal);
5646             //printf("targetx4:\n%s\nadjTargetx4:\n%s\n", targetx4.ToUniValue().write().c_str(), adjTargetx4.ToUniValue().write().c_str());
5647
5648             // loop through all those that have been zeroed in the adjusted target, and mark as satisfied
5649             for (auto &oneCur : targetx4.NonIntersectingValues(adjTargetx4).valueMap)
5650             {
5651                 //printf("satisfied x 4: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5652                 satisfied_x4.insert(oneCur.first);
5653             }
5654
5655             if (satisfied_x4.size() == nTotalTarget.valueMap.size())
5656             {
5657                 //printf("short circuit lower: lowerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5658                 break;
5659             }
5660         }
5661     }
5662
5663     std::set<uint160> satisfied_larger;
5664
5665     CCurrencyValueMap newLargerTotal;
5666     CCurrencyValueMap adjTotalTarget;
5667     std::map<std::pair<const CWalletTx *, int>, CCurrencyValueMap> largerCoins; // int is the index into the vOutputsToOptimize to remove
5668
5669     // if our lower total + larger total are not enough, no way we have enough
5670     if ((lowerTotal + largerTotal) < nTotalTarget)
5671     {
5672         return false;
5673     }
5674
5675     //printf("\nlowerTotal:\n%s\nlargerTotal:\n%s\nnewLargerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), largerTotal.ToUniValue().write().c_str(), newLargerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5676
5677     for (auto &lowerOut : lowerOuts)
5678     {
5679         totalToOptimize += lowerOut.second;
5680         vOutputsToOptimize.push_back(std::make_pair(lowerOut.second, std::make_pair(lowerOut.first.first, lowerOut.first.second)));
5681     }
5682
5683     // if all the lower amounts are just what we need, and we don't add too many inputs in the process, use them all
5684     size_t numInputsLimit = (size_t)GetArg("-mempooltxinputlimit", MAX_NUM_INPUTS_LIMIT);
5685
5686     if ((lowerTotal >= nTotalTarget && lowerTotal <= (nTotalTarget + nativeCent)) && lowerOuts.size() <= numInputsLimit)
5687     {
5688         //printf("selecting all lowers\nlowerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5689
5690         for (auto oneOut : lowerOuts)
5691         {
5692             setCoinsRet.insert(std::make_pair(oneOut.first.first, oneOut.first.second));
5693             valueRet += oneOut.first.first->vout[oneOut.first.second].ReserveOutValue();
5694             nativeValueRet += oneOut.first.first->vout[oneOut.first.second].nValue;
5695         }
5696         return true;
5697     }
5698
5699     //printf("\nlowerTotal:\n%s\nlargerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), largerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5700
5701     std::map<std::pair<const CWalletTx *, int>, CReserveOutSelectionInfo> added;
5702     largerTotal.valueMap.clear();
5703     CCurrencyValueMap adjustedTarget;
5704     std::set<uint160> satisfied;
5705
5706     // short circuit best fit check with any exact amounts we may have
5707     if (multiSatisfy.size())
5708     {
5709         // each output for each currency will satisfy one or more currency requirements
5710         // first check those that satisfy more than one currency, then select those which are lowest value in currencies they satisfy
5711
5712         // check in reverse to check those that satisfy most first
5713         for (auto multiIt = multiSatisfy.rbegin(); multiIt != multiSatisfy.rend(); multiIt++)
5714         {
5715             // if we have 0 left, we're done
5716             if (nTotalTarget.valueMap.size() == satisfied.size())
5717             {
5718                 //printf("satisfied all currencies. lowerTotal:\n%s\n", largerTotal.ToUniValue().write().c_str());
5719                 break;
5720             }
5721
5722             // consider "satisfying" an exact match of any currency in the adjusted request, otherwise, we should fall through to the best fit solver
5723             int newFound = 0;
5724             for (auto &oneCurID : multiIt->second.first)
5725             {
5726                 if (!satisfied.count(oneCurID) &&
5727                     multiIt->second.second.outVal.valueMap[oneCurID] == adjustedTarget.valueMap[oneCurID])
5728                 {
5729                     newFound++;
5730                 }
5731             }
5732
5733             std::pair<const CWalletTx *, unsigned int> outPair({multiIt->second.second.pWtx, multiIt->second.second.n});
5734
5735             // if we don't satisfy any new currency with this output, don't add it as we care more if singles are lower as a priotity
5736             if (!newFound || added.count(outPair))
5737             {
5738                 continue;
5739             }
5740
5741             // this satisfies at least 1 new currency, so use it and also reduce other currencies by all amounts that it includes
5742             // don't check it again when looking later
5743             added.insert(std::make_pair(outPair, multiIt->second.second));
5744
5745             // add all currency values in the transaction, as some may partially satisfy, and we should early out when we have enough
5746             // printf("multiIt->second.second.outVal:\n%s\n", multiIt->second.second.outVal.ToUniValue().write().c_str());
5747             CCurrencyValueMap newAdded(multiIt->second.second.outVal.IntersectingValues(nTotalTarget));
5748             largerTotal += newAdded;
5749             largerOuts.erase(outPair);
5750
5751             // printf("adjustedTarget:\n%s\ntotalAdded:\n%s\n", adjustedTarget.ToUniValue().write().c_str(), totalAdded.ToUniValue().write().c_str());
5752
5753             // printf("adjustedTarget:\n%s\n", adjustedTarget.ToUniValue().write().c_str());
5754             // printf("nTotalTarget.NonIntersectingValues(adjustedTarget):\n%s\n", nTotalTarget.NonIntersectingValues(adjustedTarget).ToUniValue().write().c_str());
5755
5756             adjustedTarget = nTotalTarget.SubtractToZero(largerTotal);
5757
5758             // loop through all those that have been zeroed in the adjusted target, and mark as satisfied
5759             for (auto &oneCur : nTotalTarget.NonIntersectingValues(adjustedTarget).valueMap)
5760             {
5761                 //printf("satisfied: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5762                 satisfied.insert(oneCur.first);
5763             }
5764         }
5765     }
5766
5767     // if we've satisfied all currency requirements with larger outputs that fit well, use what we have and be done
5768     if (satisfied.size() == nTotalTarget.valueMap.size())
5769     {
5770         for (auto &oneOut : added)
5771         {
5772             setCoinsRet.insert(std::make_pair(oneOut.second.pWtx, oneOut.second.n));
5773             valueRet += oneOut.second.outVal;
5774         }
5775         auto vRetIt = valueRet.valueMap.find(ASSETCHAINS_CHAINID);
5776         if (vRetIt != valueRet.valueMap.end())
5777         {
5778             nativeValueRet = vRetIt->second;
5779             valueRet.valueMap.erase(vRetIt);
5780         }
5781         return true;
5782     }
5783
5784     // fill up lower outputs with larger as well to ensure fill
5785     // those we add from multisatisfy check will be removed from optimized selection
5786     for (auto &oneCurID : satisfied)
5787     {
5788         satisfied_x4.insert(oneCurID);
5789     }
5790     for (auto &largerOut : largerOuts)
5791     {
5792         COutput thisOutput(largerOut.first.first, largerOut.first.second, 0, true);
5793         if (lowerOuts.count(std::make_pair(largerOut.first.first, largerOut.first.second)))
5794         {
5795             continue;
5796         }
5797         // if we have more, they only go into the lower, if they have
5798         // coins in the currencies where we are not satisfied
5799
5800         //printf("targetx4:\n%s\nlowerTotal:\n%s\nlargerOut.second:\n%s\n", targetx4.ToUniValue().write().c_str(), lowerTotal.ToUniValue().write().c_str(), largerOut.second.ToUniValue().write().c_str());
5801
5802         bool useThis = false;
5803         for (auto &oneCur : largerOut.second.IntersectingValues(nTotalTarget).valueMap)
5804         {
5805             if (!satisfied.count(oneCur.first) && !satisfied_x4.count(oneCur.first))
5806             {
5807                 useThis = true;
5808             }
5809         }
5810
5811         if (useThis)
5812         {
5813             CReserveOutSelectionInfo coin(largerOut.first.first, largerOut.first.second, largerOut.second);
5814
5815             for (auto &oneCur : largerOut.second.valueMap)
5816             {
5817                 coinsLargestLower[oneCur.first].insert(std::make_pair(oneCur.second, coin));
5818             }
5819
5820             lowerOuts.insert(std::make_pair(std::make_pair(largerOut.first.first, largerOut.first.second), largerOut.second));
5821
5822             lowerTotal += largerOut.second;
5823
5824             CCurrencyValueMap adjTargetx4 = targetx4.SubtractToZero(lowerTotal);
5825             //printf("targetx4:\n%s\nadjTargetx4:\n%s\n", targetx4.ToUniValue().write().c_str(), adjTargetx4.ToUniValue().write().c_str());
5826
5827             // loop through all those that have been zeroed in the adjusted target, and mark as satisfied
5828             for (auto &oneCur : targetx4.NonIntersectingValues(adjTargetx4).valueMap)
5829             {
5830                 // don't consider it satisfied x4, unless we have at least 4 entries to choose from
5831                 if (coinsLargestLower.count(oneCur.first) && coinsLargestLower[oneCur.first].size() >= 4)
5832                 {
5833                     //printf("satisfied x 4: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5834                     satisfied_x4.insert(oneCur.first);
5835                 }
5836             }
5837             totalToOptimize += largerOut.second;
5838             vOutputsToOptimize.push_back(std::make_pair(largerOut.second, std::make_pair(largerOut.first.first, largerOut.first.second)));
5839         }
5840     }
5841
5842     //printf("\nlargerTotal:\n%s\n", largerTotal.ToUniValue().write().c_str());
5843     // printf("adjustedTarget:\n%s\n", adjustedTarget.ToUniValue().write().c_str());
5844
5845     // make new vector without those we have added due to exact fit, and use remaining and adjusted target to satisfy requests
5846     std::vector<int> vOutputsToRemove;
5847     CCurrencyValueMap removedValue;
5848     if (added.size())
5849     {
5850         for (int i = 0; i < vOutputsToOptimize.size(); i++)
5851         {
5852             if (added.count(vOutputsToOptimize[i].second))
5853             {
5854                 vOutputsToRemove.push_back(i);
5855                 removedValue += vOutputsToOptimize[i].first;
5856             }
5857         }
5858
5859         for (auto &oneOutput : added)
5860         {
5861             setCoinsRet.insert(std::make_pair(oneOutput.second.pWtx, oneOutput.second.n));
5862             valueRet += oneOutput.second.outVal;
5863         }
5864         auto vRetIt = valueRet.valueMap.find(ASSETCHAINS_CHAINID);
5865         if (vRetIt != valueRet.valueMap.end())
5866         {
5867             nativeValueRet = vRetIt->second;
5868             valueRet.valueMap.erase(vRetIt);
5869         }
5870     }
5871
5872     // remove all that we've already added leaving a vector of those that we need to optimize
5873     for (int i = vOutputsToRemove.size() - 1; i >= 0; i--)
5874     {
5875         vOutputsToOptimize.erase(vOutputsToOptimize.begin() + vOutputsToRemove[i]);
5876     }
5877
5878     totalToOptimize = totalToOptimize.SubtractToZero(removedValue);
5879     CCurrencyValueMap newOptimizationTarget = nTotalTarget.SubtractToZero(largerTotal);
5880
5881     //printf("totalToOptimize:\n%s\nnewOptimizationTarget:\n%s\n", totalToOptimize.ToUniValue().write().c_str(), newOptimizationTarget.ToUniValue().write().c_str());
5882     /* for (int i = 0; i < vOutputsToOptimize.size(); i++)
5883     {
5884         printf("output #%d:\nreserves:\n%s\nnative:\n%s\n", 
5885             i, 
5886             vOutputsToOptimize[i].first.ToUniValue().write().c_str(), 
5887             ValueFromAmount(vOutputsToOptimize[i].second.first->vout[vOutputsToOptimize[i].second.second].nValue).write().c_str());
5888     } */
5889
5890     vector<char> vfBest;
5891     CCurrencyValueMap bestTotals;
5892
5893     ApproximateBestReserveSubset(vOutputsToOptimize, totalToOptimize, newOptimizationTarget, vfBest, bestTotals, 1000);
5894     if (bestTotals != newOptimizationTarget && totalToOptimize >= newOptimizationTarget + nativeCent)
5895     {
5896         //printf("bestTotals:\n%s\ntotalToOptimize:\n%s\nnewOptimizationTarget:\n%s\n", bestTotals.ToUniValue().write().c_str(), totalToOptimize.ToUniValue().write().c_str(), (newOptimizationTarget + nativeCent).ToUniValue().write().c_str());
5897         ApproximateBestReserveSubset(vOutputsToOptimize, totalToOptimize, newOptimizationTarget + nativeCent, vfBest, bestTotals, 1000);
5898     }
5899
5900     for (unsigned int i = 0; i < vOutputsToOptimize.size(); i++)
5901     {
5902         if (vfBest[i])
5903         {
5904             setCoinsRet.insert(vOutputsToOptimize[i].second);
5905             valueRet += vOutputsToOptimize[i].second.first->vout[vOutputsToOptimize[i].second.second].ReserveOutValue();
5906             nativeValueRet += vOutputsToOptimize[i].second.first->vout[vOutputsToOptimize[i].second.second].nValue;
5907             /* printf("one selected\ntxid: %s, output: %d\nvalueOut: %s\n", 
5908                     vOutputsToOptimize[i].second.first->GetHash().GetHex().c_str(), 
5909                     vOutputsToOptimize[i].second.second, 
5910                     vOutputsToOptimize[i].first.ToUniValue().write(1,2).c_str()); */
5911         }
5912     }
5913
5914     CCurrencyValueMap checkReturn(valueRet);
5915     checkReturn.valueMap[ASSETCHAINS_CHAINID] = nativeValueRet;
5916
5917     if (checkReturn.IntersectingValues(nTotalTarget) < nTotalTarget)
5918     {
5919         return false;
5920     }
5921
5922     LogPrint("selectcoins", "SelectCoins() best subset: ");
5923     for (unsigned int i = 0; i < vOutputsToOptimize.size(); i++)
5924     {
5925         if (vfBest[i])
5926         {
5927             LogPrint("selectcoins", "%s", FormatMoney(vOutputsToOptimize[i].first.valueMap[targetValues.valueMap.begin()->first]));
5928         }
5929     }
5930     LogPrint("selectcoins", "total %s\n", FormatMoney(bestTotals.valueMap[targetValues.valueMap.begin()->first]));
5931
5932     return true;
5933 }
5934
5935 bool CWallet::SelectReserveCoins(const CCurrencyValueMap& targetReserveValues, 
5936                                  CAmount targetNativeValue,
5937                                  set<pair<const CWalletTx*,unsigned int> >& setCoinsRet,
5938                                  CCurrencyValueMap &valueRet,
5939                                  CAmount &nativeRet,
5940                                  bool& fOnlyCoinbaseCoinsRet,
5941                                  bool& fNeedCoinbaseCoinsRet,
5942                                  const CCoinControl* coinControl,
5943                                  const CTxDestination *pOnlyFromDest) const
5944 {
5945     // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
5946
5947     vector<COutput> vCoinsNoCoinbase, vCoinsWithCoinbase;
5948     AvailableReserveCoins(vCoinsNoCoinbase, true, coinControl, false, true, pOnlyFromDest, &targetReserveValues);
5949     AvailableReserveCoins(vCoinsWithCoinbase, true, coinControl, true, true, pOnlyFromDest, &targetReserveValues);
5950     fOnlyCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
5951
5952     // coinbase protection forcing them to be spent only to z-addresses ended
5953     // when identities were released
5954     bool fProtectCoinbase = false;
5955
5956     vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
5957
5958     // Output parameter fNeedCoinbaseCoinsRet is set to true if coinbase utxos need to be spent to meet target amount
5959     if (fProtectCoinbase && vCoinsWithCoinbase.size() > vCoinsNoCoinbase.size()) {
5960         CCurrencyValueMap reserveValues;
5961         CAmount nativeValue = 0;
5962         for (const COutput& out : vCoinsNoCoinbase) {
5963             if (!out.fSpendable) {
5964                 continue;
5965             }
5966             nativeValue += out.tx->vout[out.i].nValue;
5967             reserveValues += out.tx->vout[out.i].ReserveOutValue();
5968         }
5969         if (reserveValues < targetReserveValues || nativeValue < targetNativeValue) {
5970             CCurrencyValueMap reserveValuesWithCoinbase;
5971             CAmount nativeValueWithCoinbase = 0;
5972             for (const COutput& out : vCoinsWithCoinbase) {
5973                 if (!out.fSpendable) {
5974                     continue;
5975                 }
5976                 reserveValuesWithCoinbase += out.tx->vout[out.i].ReserveOutValue();
5977                 nativeValueWithCoinbase += out.tx->vout[out.i].nValue;
5978             }
5979             fNeedCoinbaseCoinsRet = (reserveValuesWithCoinbase >= targetReserveValues) && (nativeValueWithCoinbase >= targetNativeValue);
5980         }
5981     }
5982
5983     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
5984     if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
5985     {
5986         BOOST_FOREACH(const COutput& out, vCoins)
5987         {
5988             if (!out.fSpendable)
5989                  continue;
5990             valueRet += out.tx->vout[out.i].ReserveOutValue();
5991             nativeRet += out.tx->vout[out.i].nValue;
5992             setCoinsRet.insert(make_pair(out.tx, out.i));
5993         }
5994         return (valueRet >= targetReserveValues) && (nativeRet >= targetNativeValue);
5995     }
5996
5997     // calculate value from preset inputs and store them
5998     set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
5999     CCurrencyValueMap valueFromPresetInputs;
6000     CAmount nativeValueFromPresets = 0;
6001
6002     std::vector<COutPoint> vPresetInputs;
6003     if (coinControl)
6004         coinControl->ListSelected(vPresetInputs);
6005     BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
6006     {
6007         map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
6008         if (it != mapWallet.end())
6009         {
6010             const CWalletTx* pcoin = &it->second;
6011             // Clearly invalid input, fail
6012             if (pcoin->vout.size() <= outpoint.n)
6013                 return false;
6014             valueFromPresetInputs += pcoin->vout[outpoint.n].ReserveOutValue();
6015             nativeValueFromPresets += pcoin->vout[outpoint.n].nValue;
6016             setPresetCoins.insert(make_pair(pcoin, outpoint.n));
6017         } else
6018             return false; // TODO: Allow non-wallet inputs
6019     }
6020
6021     // remove preset inputs from vCoins
6022     for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
6023     {
6024         if (setPresetCoins.count(make_pair(it->tx, it->i)))
6025             it = vCoins.erase(it);
6026         else
6027             ++it;
6028     }
6029
6030     bool retval = false;
6031     if ( targetNativeValue <= nativeRet &&
6032          targetReserveValues <= targetReserveValues.IntersectingValues(valueFromPresetInputs) && targetNativeValue <= nativeValueFromPresets )
6033         retval = true;
6034     else if ( SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 1, 6, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
6035         retval = true;
6036     else if ( SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 1, 1, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
6037         retval = true;
6038     else if ( bSpendZeroConfChange && SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 0, 1, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
6039         retval = true;
6040     // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
6041     setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
6042     // add preset inputs to the total value selected
6043     valueRet += valueFromPresetInputs;
6044     nativeRet += nativeValueFromPresets;
6045     return retval;
6046 }
6047
6048 bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason)
6049 {
6050     vector<CRecipient> vecSend;
6051
6052     // Turn the txout set into a CRecipient vector
6053     BOOST_FOREACH(const CTxOut& txOut, tx.vout)
6054     {
6055         CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false};
6056         vecSend.push_back(recipient);
6057     }
6058
6059     CCoinControl coinControl;
6060     coinControl.fAllowOtherInputs = true;
6061     BOOST_FOREACH(const CTxIn& txin, tx.vin)
6062         coinControl.Select(txin.prevout);
6063
6064     CReserveKey reservekey(this);
6065     CWalletTx wtx;
6066
6067     if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
6068         return false;
6069
6070     if (nChangePosRet != -1)
6071         tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
6072
6073     // Add new txins (keeping original txin scriptSig/order)
6074     BOOST_FOREACH(const CTxIn& txin, wtx.vin)
6075     {
6076         bool found = false;
6077         BOOST_FOREACH(const CTxIn& origTxIn, tx.vin)
6078         {
6079             if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
6080             {
6081                 found = true;
6082                 break;
6083             }
6084         }
6085         if (!found)
6086             tx.vin.push_back(txin);
6087     }
6088
6089     return true;
6090 }
6091
6092 bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
6093                                 int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
6094 {
6095     uint64_t interest2 = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0;
6096     BOOST_FOREACH (const CRecipient& recipient, vecSend)
6097     {
6098         if (nValue < 0 || recipient.nAmount < 0)
6099         {
6100             strFailReason = _("Transaction amounts must be positive");
6101             return false;
6102         }
6103         nValue += recipient.nAmount;
6104
6105         if (recipient.fSubtractFeeFromAmount)
6106             nSubtractFeeFromAmount++;
6107     }
6108     if (vecSend.empty() || nValue < 0)
6109     {
6110         strFailReason = _("Transaction amounts must be positive");
6111         return false;
6112     }
6113
6114     wtxNew.fTimeReceivedIsTxTime = true;
6115     wtxNew.BindWallet(this);
6116     int nextBlockHeight = chainActive.Height() + 1;
6117
6118     CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
6119     txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
6120
6121     // Activates after Overwinter network upgrade
6122     if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) {
6123         if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){
6124             strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD.");
6125             return false;
6126         }
6127     }
6128
6129     unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
6130     if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) {
6131         max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
6132     }
6133
6134     // Discourage fee sniping.
6135     //
6136     // However because of a off-by-one-error in previous versions we need to
6137     // neuter it by setting nLockTime to at least one less than nBestHeight.
6138     // Secondly currently propagation of transactions created for block heights
6139     // corresponding to blocks that were just mined may be iffy - transactions
6140     // aren't re-accepted into the mempool - we additionally neuter the code by
6141     // going ten blocks back. Doesn't yet do anything for sniping, but does act
6142     // to shake out wallet bugs like not showing nLockTime'd transactions at
6143     // all.
6144     txNew.nLockTime = std::max(0, chainActive.Height() - 10);
6145
6146     // Secondly occasionally randomly pick a nLockTime even further back, so
6147     // that transactions that are delayed after signing for whatever reason,
6148     // e.g. high-latency mix networks and some CoinJoin implementations, have
6149     // better privacy.
6150     if (GetRandInt(10) == 0)
6151         txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
6152
6153     assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
6154     assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
6155
6156     {
6157         LOCK2(cs_main, cs_wallet);
6158         {
6159             nFeeRet = 0;
6160             while (true)
6161             {
6162                 //interest = 0;
6163                 txNew.vin.clear();
6164                 txNew.vout.clear();
6165                 wtxNew.fFromMe = true;
6166                 nChangePosRet = -1;
6167                 bool fFirst = true;
6168
6169                 CAmount nTotalValue = nValue;
6170                 if (nSubtractFeeFromAmount == 0)
6171                     nTotalValue += nFeeRet;
6172                 double dPriority = 0;
6173                 // vouts to the payees
6174                 BOOST_FOREACH (const CRecipient& recipient, vecSend)
6175                 {
6176                     CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
6177
6178                     if (recipient.fSubtractFeeFromAmount)
6179                     {
6180                         txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
6181
6182                         if (fFirst) // first receiver pays the remainder not divisible by output count
6183                         {
6184                             fFirst = false;
6185                             txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
6186                         }
6187                     }
6188
6189                     COptCCParams p;
6190
6191                     if (txout.IsDust(::minRelayTxFee) && !(txout.nValue == 0 && txout.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode != EVAL_NONE))
6192                     {
6193                         if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
6194                         {
6195                             if (txout.nValue < 0)
6196                                 strFailReason = _("The transaction amount is too small to pay the fee");
6197                             else
6198                                 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
6199                         }
6200                         else
6201                             strFailReason = _("Transaction amount too small");
6202                         return false;
6203                     }
6204                     txNew.vout.push_back(txout);
6205                 }
6206
6207                 // Choose coins to use
6208                 set<pair<const CWalletTx*,unsigned int> > setCoins;
6209                 CAmount nValueIn = 0;
6210                 bool fOnlyProtectedCoinbaseCoins = false;
6211                 bool fNeedProtectedCoinbaseCoins = false;
6212                 interest2 = 0;
6213                 if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyProtectedCoinbaseCoins, fNeedProtectedCoinbaseCoins, coinControl))
6214                 {
6215                     if (fOnlyProtectedCoinbaseCoins) {
6216                         strFailReason = _("Coinbase funds earned while shielding protection is active can only be sent to a zaddr");
6217                     } else if (fNeedProtectedCoinbaseCoins) {
6218                         strFailReason = _("Insufficient funds, protected coinbase funds can only be spent after they have been sent to a zaddr");
6219                     } else {
6220                         strFailReason = _("Insufficient funds");
6221                     }
6222                     return false;
6223                 }
6224                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
6225                 {
6226                     CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
6227                     //The coin age after the next block (depth+1) is used instead of the current,
6228                     //reflecting an assumption the user would accept a bit more delay for
6229                     //a chance at a free transaction.
6230                     //But mempool inputs might still be in the mempool, so their age stays 0
6231                     //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN);
6232                     if ( KOMODO_EXCHANGEWALLET == 0 && ASSETCHAINS_SYMBOL[0] == 0 )
6233                     {
6234                         interest2 += pcoin.first->vout[pcoin.second].interest;
6235                         //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN);
6236                     }
6237                     int age = pcoin.first->GetDepthInMainChain();
6238                     if (age != 0)
6239                         age += 1;
6240                     dPriority += (double)nCredit * age;
6241                 }
6242                 //if ( KOMODO_EXCHANGEWALLET != 0 )
6243                 //{
6244                     //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN);
6245                     //interest = 0; // interest2 also
6246                 //}
6247                 if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 )
6248                 {
6249                     CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG;
6250                     CTxOut newTxOut(interest2,scriptDonation);
6251                     int32_t nDonationPosRet = txNew.vout.size() - 1; // dont change first or last
6252                     vector<CTxOut>::iterator position = txNew.vout.begin()+nDonationPosRet;
6253                     txNew.vout.insert(position, newTxOut);
6254                     interest2 = 0;
6255                 }
6256                 CAmount nChange = (nValueIn - nValue + interest2);
6257                 //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);
6258                 if (nSubtractFeeFromAmount == 0)
6259                     nChange -= nFeeRet;
6260
6261                 if (nChange > 0)
6262                 {
6263                     // Fill a vout to ourself
6264                     // TODO: pass in scriptChange instead of reservekey so
6265                     // change transaction isn't always pay-to-bitcoin-address
6266                     CScript scriptChange;
6267
6268                     // coin control: send change to custom address
6269                     if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
6270                         scriptChange = GetScriptForDestination(coinControl->destChange);
6271
6272                     // no coin control: send change to newly generated address
6273                     else
6274                     {
6275                         // Note: We use a new key here to keep it from being obvious which side is the change.
6276                         //  The drawback is that by not reusing a previous key, the change may be lost if a
6277                         //  backup is restored, if the backup doesn't have the new private key for the change.
6278                         //  If we reused the old key, it would be possible to add code to look for and
6279                         //  rediscover unknown transactions that were written with keys of ours to recover
6280                         //  post-backup change.
6281
6282                         // Reserve a new key pair from key pool
6283                         CPubKey vchPubKey;
6284                         extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
6285                         if ( USE_EXTERNAL_PUBKEY == 0 )
6286                         {
6287                             bool ret;
6288                             ret = reservekey.GetReservedKey(vchPubKey);
6289                             assert(ret); // should never fail, as we just unlocked
6290                             scriptChange = GetScriptForDestination(vchPubKey.GetID());
6291                         }
6292                         else
6293                         {
6294                             //fprintf(stderr,"use notary pubkey\n");
6295                             scriptChange = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
6296                         }
6297                     }
6298
6299                     CTxOut newTxOut(nChange, scriptChange);
6300
6301                     // We do not move dust-change to fees, because the sender would end up paying more than requested.
6302                     // This would be against the purpose of the all-inclusive feature.
6303                     // So instead we raise the change and deduct from the recipient.
6304                     if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee))
6305                     {
6306                         CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue;
6307                         newTxOut.nValue += nDust; // raise change until no more dust
6308                         for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
6309                         {
6310                             if (vecSend[i].fSubtractFeeFromAmount)
6311                             {
6312                                 txNew.vout[i].nValue -= nDust;
6313                                 if (txNew.vout[i].IsDust(::minRelayTxFee))
6314                                 {
6315                                     strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
6316                                     return false;
6317                                 }
6318                                 break;
6319                             }
6320                         }
6321                     }
6322
6323                     // Never create dust outputs; if we would, just
6324                     // add the dust to the fee. Valid cryptoconditions with a valid eval function are allowed to create outputs of 0
6325                     if (newTxOut.IsDust(::minRelayTxFee))
6326                     {
6327                         nFeeRet += nChange;
6328                         reservekey.ReturnKey();
6329                     }
6330                     else
6331                     {
6332                         nChangePosRet = txNew.vout.size() - 1; // dont change first or last
6333                         vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
6334                         txNew.vout.insert(position, newTxOut);
6335                     }
6336                 } else reservekey.ReturnKey();
6337
6338                 // Fill vin
6339                 //
6340                 // Note how the sequence number is set to max()-1 so that the
6341                 // nLockTime set above actually works.
6342                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6343                     txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
6344                                               std::numeric_limits<unsigned int>::max()-1));
6345
6346                 // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
6347                 size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
6348                 {
6349                     LOCK(cs_main);
6350                     if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) {
6351                         limit = 0;
6352                     }
6353                 }
6354                 if (limit > 0) {
6355                     size_t n = txNew.vin.size();
6356                     if (n > limit) {
6357                         strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
6358                         return false;
6359                     }
6360                 }
6361
6362                 // Grab the current consensus branch ID
6363                 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
6364
6365                 // Sign
6366                 int nIn = 0;
6367                 CTransaction txNewConst(txNew);
6368                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6369                 {
6370                     bool signSuccess;
6371                     const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
6372                     SignatureData sigdata;
6373                     if (sign)
6374                         signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, scriptPubKey), scriptPubKey, sigdata, consensusBranchId);
6375                     else
6376                         signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
6377
6378                     if (!signSuccess)
6379                     {
6380                         strFailReason = _("Signing transaction failed");
6381                         return false;
6382                     } else {
6383                         UpdateTransaction(txNew, nIn, sigdata);
6384                     }
6385
6386                     nIn++;
6387                 }
6388
6389                 unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
6390
6391                 // Remove scriptSigs if we used dummy signatures for fee calculation
6392                 if (!sign) {
6393                     BOOST_FOREACH (CTxIn& vin, txNew.vin)
6394                         vin.scriptSig = CScript();
6395                 }
6396
6397                 // Embed the constructed transaction data in wtxNew.
6398                 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
6399
6400                 // Limit size
6401                 if (nBytes >= max_tx_size)
6402                 {
6403                     strFailReason = _("Transaction too large");
6404                     return false;
6405                 }
6406
6407                 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
6408
6409                 // Can we complete this as a free transaction?
6410                 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
6411                 {
6412                     // Not enough fee: enough priority?
6413                     double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
6414                     // Not enough mempool history to estimate: use hard-coded AllowFree.
6415                     if (dPriorityNeeded <= 0 && AllowFree(dPriority))
6416                         break;
6417
6418                     // Small enough, and priority high enough, to send for free
6419                     if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
6420                         break;
6421                 }
6422
6423                 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
6424                 if ( nFeeNeeded < 5000 )
6425                     nFeeNeeded = 5000;
6426
6427                 // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
6428                 // because we must be at the maximum allowed fee.
6429                 if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
6430                 {
6431                     strFailReason = _("Transaction too large for fee policy");
6432                     return false;
6433                 }
6434
6435                 if (nFeeRet >= nFeeNeeded)
6436                     break; // Done, enough fee included.
6437
6438                 // Include more fee and try again.
6439                 nFeeRet = nFeeNeeded;
6440                 continue;
6441             }
6442         }
6443     }
6444
6445     return true;
6446 }
6447
6448 // almost the same as CreateTransaction with the difference being that input and output are assumed to be
6449 // tokens/reserve currencies, not the native currency of this chain, represented as reserve outputs for both input and output.
6450 // That means that all outputs must be reserve consuming outputs. Fee is added or converted from reserves if this is a
6451 // fractional reserve chain. Fees are calculated based on the current reserve conversion price.
6452 int CWallet::CreateReserveTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
6453                                        int& nChangePosRet, int &nChangeOutputs, std::string& strFailReason, const CCoinControl* coinControl, 
6454                                        const CTxDestination *pOnlyFromDest, bool sign)
6455 {
6456     CCurrencyValueMap totalReserveOutput;
6457     CAmount totalNativeOutput = 0;
6458
6459     CCurrencyValueMap reserveCurrencies;
6460     unsigned int nSubtractFeeFromAmount = 0;
6461
6462     // fees can only be deducted from fractional reserve outputs on fractional currency blockchains, otherwise,
6463     // Verus/Verustest must be used to cover fees.
6464     bool isVerusActive = IsVerusActive();
6465     if (!isVerusActive)
6466     {
6467         if (ConnectedChains.ReserveCurrencies().size())
6468         {
6469             for (auto &oneCur : ConnectedChains.ReserveCurrencies())
6470             {
6471                 reserveCurrencies.valueMap[oneCur.first] = 1;       // we're only testing for intersection, not value
6472             }
6473         }
6474     }
6475
6476     // make sure we have some outputs
6477     if (vecSend.empty())
6478     {
6479         strFailReason = _("Transaction must have outputs");
6480         return RPC_INVALID_PARAMETER;
6481     }
6482
6483     CCurrencyDefinition newCurrency;
6484
6485     // make sure that there are recipients, all recipients expect reserve inputs, and amounts are all non-negative
6486     BOOST_FOREACH (const CRecipient& recipient, vecSend)
6487     {
6488         COptCCParams p;
6489         if (recipient.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode == EVAL_CURRENCY_DEFINITION && p.vData.size() >= 1)
6490         {
6491             if (newCurrency.IsValid())
6492             {
6493                 strFailReason = _("A normal transaction cannot define define multiple currencies");
6494                 return RPC_INVALID_PARAMETER;
6495             }
6496             newCurrency = CCurrencyDefinition(p.vData[0]);
6497         }
6498         CCurrencyValueMap values = recipient.scriptPubKey.ReserveOutValue();
6499         CCurrencyValueMap zeroes = values - values; // zero values of the same currencies
6500
6501         if (!values.IsValid())
6502         {
6503             strFailReason = _("Output cannot have NULL currency type");
6504             return RPC_INVALID_PARAMETER;
6505         }
6506         if (values.HasNegative())
6507         {
6508             strFailReason = _("Transaction output amounts must not be negative");
6509             return RPC_INVALID_PARAMETER;
6510         }
6511
6512         totalNativeOutput += recipient.nAmount;
6513
6514         totalReserveOutput += values;
6515
6516         // if we should take from this output, it must be able to pay the fee. fail if it does not
6517         if (recipient.fSubtractFeeFromAmount && (recipient.nAmount > 0 || reserveCurrencies.Intersects(values)))
6518         {
6519             nSubtractFeeFromAmount++;
6520         }
6521         else if (recipient.fSubtractFeeFromAmount)
6522         {
6523             strFailReason = _("Cannot specify to subtract fee from amount on non-native, non-reserve currency outputs");
6524             return RPC_INVALID_PARAMETER;
6525         }
6526
6527         // make sure we have no negative totals. we do not move this outside the loop, so we can check against overflow on every iteration
6528         if (totalReserveOutput.HasNegative())
6529         {
6530             strFailReason = _("Transaction amounts must not be negative");
6531             return RPC_INVALID_PARAMETER;
6532         }
6533     }
6534
6535     if (newCurrency.IsValid())
6536     {
6537         totalReserveOutput.valueMap.erase(newCurrency.GetID());
6538     }
6539
6540     //printf("totalReserveOutput: %s\n", totalReserveOutput.ToUniValue().write(1,2).c_str());
6541
6542     int nextBlockHeight = chainActive.Height() + 1;
6543
6544     CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
6545
6546     std::vector<CTxIn> extraInputs = wtxNew.vin;
6547
6548     wtxNew.fTimeReceivedIsTxTime = true;
6549     wtxNew.BindWallet(this);
6550     txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
6551
6552     // Activates after Overwinter network upgrade
6553     if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) {
6554         if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){
6555             strFailReason = "nExpiryHeight must be less than" + std::to_string((uint32_t)TX_EXPIRY_HEIGHT_THRESHOLD);
6556             return RPC_INVALID_PARAMETER;
6557         }
6558     }
6559
6560     unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
6561     if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) {
6562         max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
6563     }
6564
6565     // Discourage fee sniping.
6566     //
6567     // However because of a off-by-one-error in previous versions we need to
6568     // neuter it by setting nLockTime to at least one less than nBestHeight.
6569     // Secondly currently propagation of transactions created for block heights
6570     // corresponding to blocks that were just mined may be iffy - transactions
6571     // aren't re-accepted into the mempool - we additionally neuter the code by
6572     // going ten blocks back. Doesn't yet do anything for sniping, but does act
6573     // to shake out wallet bugs like not showing nLockTime'd transactions at
6574     // all.
6575     txNew.nLockTime = std::max(0, chainActive.Height() - 10);
6576
6577     // Secondly occasionally randomly pick a nLockTime even further back, so
6578     // that transactions that are delayed after signing for whatever reason,
6579     // e.g. high-latency mix networks and some CoinJoin implementations, have
6580     // better privacy.
6581     if (GetRandInt(10) == 0)
6582         txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
6583
6584     assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
6585     assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
6586
6587     CCurrencyValueMap exchangeRates;
6588     {
6589         LOCK2(cs_main, cs_wallet);
6590
6591         auto currencyState = ConnectedChains.GetCurrencyState(nextBlockHeight - 1);
6592         for (int i = 0; i < currencyState.currencies.size(); i++)
6593         {
6594             exchangeRates.valueMap[currencyState.currencies[i]] = currencyState.PriceInReserve(i);
6595         }
6596
6597         nFeeRet = 5000;
6598         while (true)
6599         {
6600             //interest = 0;
6601             txNew.vin.clear();
6602             txNew.vout.clear();
6603             wtxNew.fFromMe = true;
6604             nChangePosRet = -1;
6605             nChangeOutputs = 0;
6606             bool fFirst = true;
6607
6608             // dust threshold of reserve may be different than native coin, if so, convert
6609             CAmount dustThreshold;
6610
6611             CAmount nTotalNativeValue = totalNativeOutput;
6612             CCurrencyValueMap totalReserveValue = totalReserveOutput;
6613
6614             if (nSubtractFeeFromAmount == 0)
6615                 nTotalNativeValue += nFeeRet;
6616
6617             double dPriority = 0;
6618             // vouts to the payees
6619             BOOST_FOREACH (const CRecipient& recipient, vecSend)
6620             {
6621                 // native output value for a reserve output is generally 0. fees are paid by converting from
6622                 // reserve token and the difference between input and output in reserve is the fee
6623                 // the actual reserve token output value is in the scriptPubKey
6624                 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
6625                 CAmount nativeEquivalent = txout.nValue;
6626
6627                 // here, if we know that it isn't an opret, it will have an output that expects input
6628                 if (!recipient.scriptPubKey.IsOpReturn())
6629                 {
6630                     COptCCParams p;
6631                     CCurrencyValueMap reserveOutput = recipient.scriptPubKey.ReserveOutValue(p);
6632                     CCurrencyValueMap relevantReserves;
6633
6634                     if (recipient.fSubtractFeeFromAmount)
6635                     {
6636                         CAmount subFee = nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
6637
6638                         if (fFirst) // first receiver pays the remainder not divisible by output count
6639                         {
6640                             fFirst = false;
6641                             subFee += nFeeRet % nSubtractFeeFromAmount;
6642                         }
6643
6644                         if (subFee <= txout.nValue)
6645                         {
6646                             txout.nValue -= subFee;
6647                         }
6648                         else if ((relevantReserves = reserveOutput.IntersectingValues(reserveCurrencies)).valueMap.size())
6649                         {
6650                             // if we will subtract from more than one currency, divide fee among them equally
6651                             CAmount subSubFee = subFee / relevantReserves.valueMap.size();
6652                             CAmount extraFee = subFee % relevantReserves.valueMap.size();
6653                             // TODO: this does not support multi-currency, since the outputs do not. it will need
6654                             // to be checked when we enable multi-currency outputs
6655                             for (auto &oneCur : relevantReserves.valueMap)
6656                             {
6657                                 auto it = exchangeRates.valueMap.find(oneCur.first);
6658                                 assert(it != exchangeRates.valueMap.end());
6659                                 reserveOutput.valueMap[it->first] -= currencyState.NativeToReserveRaw(subFee + (extraFee ? 1 : 0), it->second);
6660                                 if (extraFee)
6661                                 {
6662                                     extraFee--;
6663                                 }
6664                             }
6665                             txout.scriptPubKey.SetReserveOutValue(reserveOutput);
6666                         }
6667                         else
6668                         {
6669                             // asking to pay a fee on an output, but not being able to is not accepted, should
6670                             // never get here, as it should have been checked above
6671                             strFailReason = "Cannot subtract fee from amount on non-native, non-reserve currency outputs";
6672                             return RPC_INVALID_PARAMETER;
6673                         }
6674                     }
6675
6676                     dustThreshold = txout.GetDustThreshold(::minRelayTxFee);
6677
6678                     // only non-crypto condition, and normal reserve outputs are subject to dust limitations
6679                     if (!p.IsValid() || 
6680                         p.evalCode == EVAL_RESERVE_OUTPUT || 
6681                         p.evalCode == EVAL_RESERVE_DEPOSIT || 
6682                         p.evalCode == EVAL_RESERVE_EXCHANGE || 
6683                         p.evalCode == EVAL_NONE)
6684                     {
6685                         // add all values to a native equivalent
6686                         // reserve currencies have a native value as well
6687                         if (exchangeRates.IntersectingValues(reserveOutput).valueMap.size())
6688                         {
6689                             nativeEquivalent += currencyState.ReserveToNativeRaw(relevantReserves, exchangeRates.AsCurrencyVector(currencyState.currencies));
6690                         }
6691                         else
6692                         {
6693                             nativeEquivalent += reserveOutput.valueMap.size() ? reserveOutput.valueMap.begin()->second : 0;
6694                         }
6695                         
6696                         if (nativeEquivalent < dustThreshold)
6697                         {
6698                             if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
6699                             {
6700                                 if (nativeEquivalent < 0)
6701                                     strFailReason = _("The transaction amount is too small to pay the fee");
6702                                 else
6703                                     strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
6704                             }
6705                             else
6706                                 strFailReason = _("Transaction amount too small");
6707                             return RPC_INVALID_PARAMETER;
6708                         }
6709                     }
6710                 }
6711                 txNew.vout.push_back(txout);
6712             }
6713
6714             // Choose coins to use
6715             set<pair<const CWalletTx*,unsigned int> > setCoins;
6716             CCurrencyValueMap totalValueIn;
6717             CAmount totalNativeValueIn = 0;
6718             bool fOnlyCoinbaseCoins = false;
6719             bool fNeedCoinbaseCoins = false;
6720
6721             if (!SelectReserveCoins(totalReserveValue, 
6722                                     nTotalNativeValue, 
6723                                     setCoins, 
6724                                     totalValueIn, 
6725                                     totalNativeValueIn, 
6726                                     fOnlyCoinbaseCoins, 
6727                                     fNeedCoinbaseCoins, 
6728                                     coinControl,
6729                                     pOnlyFromDest))
6730             {
6731                 strFailReason = _("Insufficient funds");
6732                 return RPC_WALLET_INSUFFICIENT_FUNDS;
6733             }
6734
6735             /*
6736             if (totalValueIn.valueMap.count(ASSETCHAINS_CHAINID))
6737             {
6738                 for (auto oneOut : setCoins)
6739                 {
6740                     UniValue oneTxObj(UniValue::VOBJ);
6741                     TxToUniv(*oneOut.first, uint256(), oneTxObj);
6742                     printf("TRANSACTION\n%s\n", oneTxObj.write(1,2).c_str());
6743                 }
6744                 printf("totalValueIn: %s\ntotalReserveValue: %s\n", totalValueIn.ToUniValue().write().c_str(), totalReserveValue.ToUniValue().write().c_str());
6745             }
6746             */
6747
6748             std::vector<std::pair<std::pair<const CWalletTx*, unsigned int>, CAmount>> coinsWithEquivalentNative;
6749             if (reserveCurrencies.valueMap.size())
6750             {
6751                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
6752                 {
6753                     CAmount nCredit = pcoin.first->vout[pcoin.second].nValue + 
6754                                     currencyState.ReserveToNativeRaw(reserveCurrencies.IntersectingValues(pcoin.first->vout[pcoin.second].ReserveOutValue()), 
6755                                                                     exchangeRates.AsCurrencyVector(currencyState.currencies));
6756                     coinsWithEquivalentNative.push_back(make_pair(pcoin, nCredit));
6757                 }
6758             }
6759
6760             CCurrencyValueMap reserveChange = totalValueIn - totalReserveValue;
6761
6762             //printf("reservechange: %s\ntotalvaluein: %s\n", reserveChange.ToUniValue().write(1,2).c_str(), totalValueIn.ToUniValue().write(1,2).c_str());
6763
6764             CCurrencyValueMap convertibleChange = reserveCurrencies.IntersectingValues(reserveChange);
6765             CAmount nChange = totalNativeValueIn - nTotalNativeValue;
6766             CAmount nConvertedReserveChange = 0;
6767
6768             // /printf("tokenChange: %s\nnativeChange: %s\n", reserveChange.ToUniValue().write().c_str(), ValueFromAmount(nChange).write().c_str());
6769
6770             // if we will try to take the fee from change
6771             if (nSubtractFeeFromAmount == 0)
6772             {
6773                 if (nChange < nFeeRet && convertibleChange.valueMap.size())
6774                 {
6775                     nConvertedReserveChange = currencyState.ReserveToNativeRaw(convertibleChange, 
6776                                                                                 exchangeRates.AsCurrencyVector(currencyState.currencies));
6777                 }
6778                 nChange -= nFeeRet;
6779             }
6780
6781             if ((nChange + nConvertedReserveChange > 0) || (reserveChange > CCurrencyValueMap()))
6782             {
6783                 // if we can and need to convert reserves, adjust reserve change output amounts as needed
6784                 if (nChange < 0 && convertibleChange.valueMap.size())
6785                 {
6786                     // no native change output, so, convert what's needed and make reserve output(s)
6787                     // attempt to convert equally across currencies, and if we fail, take the rest as
6788                     // first come, first served
6789                     CAmount nChangePerCur = -nChange / convertibleChange.valueMap.size();
6790                     CAmount nChangeMod = -nChange % convertibleChange.valueMap.size();
6791                     CAmount remainder = 0;
6792                     nChange = 0;
6793                     for (int i = 0; i < currencyState.currencies.size(); i++)
6794                     {
6795                         auto it = reserveChange.valueMap.find(currencyState.currencies[i]);
6796                         if (it != reserveChange.valueMap.end())
6797                         {
6798                             CAmount feeAsReserve = currencyState.NativeToReserve(nChangePerCur + (nChangeMod ? 1 : 0), i);
6799                             if (it->second - feeAsReserve <= 0)
6800                             {
6801                                 // if we don't have enough reserve in this currency for its part of the fee, we will
6802                                 // take it all, and then take more from the other currencies as needed
6803                                 remainder += currencyState.ReserveToNative(feeAsReserve - it->second, i);
6804                                 reserveChange.valueMap.erase(it);
6805                             }
6806                             else
6807                             {
6808                                 it->second -= feeAsReserve;
6809                             }
6810                         }
6811                     }
6812                     // if we have any fee left to convert because we were short on some currency, take it
6813                     // from the remaining reserves in change
6814                     if (remainder)
6815                     {
6816                         for (int i = 0; i < currencyState.currencies.size(); i++)
6817                         {
6818                             auto it = reserveChange.valueMap.find(currencyState.currencies[i]);
6819                             if (it != reserveChange.valueMap.end())
6820                             {
6821                                 CAmount feeAsReserve = currencyState.NativeToReserve(remainder, i);
6822                                 if (it->second - feeAsReserve <= 0)
6823                                 {
6824                                     // if we don't have enough reserve in this currency for its part of the fee, we will
6825                                     // take it all, and then take more from the other currencies as needed
6826                                     reserveChange.valueMap.erase(it);
6827                                     remainder -= currencyState.ReserveToNative(it->second, i);
6828                                 }
6829                                 else
6830                                 {
6831                                     it->second -= feeAsReserve;
6832                                     break;
6833                                 }
6834                             }
6835                         }
6836                     }
6837                 }
6838
6839                 // coin control: send change to custom address
6840
6841                 // reserve tokens can currently only be sent to public keys or addresses that are in the current wallet
6842                 // since reserve token outputs are CCs by definition
6843                 CTxDestination changeDest;
6844                 if (coinControl && coinControl->destChange.which() != COptCCParams::ADDRTYPE_INVALID)
6845                 {
6846                     changeDest = coinControl->destChange;
6847                 }
6848                 else
6849                 {
6850                     // no coin control: send change to newly generated address
6851
6852                     // Note: We use a new key here to keep it from being obvious which side is the change.
6853                     //  The drawback is that by not reusing a previous key, the change may be lost if a
6854                     //  backup is restored, if the backup doesn't have the new private key for the change.
6855                     //  If we reused the old key, it would be possible to add code to look for and
6856                     //  rediscover unknown transactions that were written with keys of ours to recover
6857                     //  post-backup change.
6858
6859                     // Reserve a new key pair from key pool
6860                     extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
6861                     CPubKey pubKey;
6862                     if ( USE_EXTERNAL_PUBKEY != 0 )
6863                     {
6864                         //fprintf(stderr,"use notary pubkey\n");
6865                         pubKey = CPubKey(ParseHex(NOTARY_PUBKEY));
6866                         changeDest = CTxDestination(pubKey);
6867                     }
6868                     else if (pOnlyFromDest && pOnlyFromDest->which() == COptCCParams::ADDRTYPE_ID)
6869                     {
6870                         changeDest = *pOnlyFromDest;
6871                     }
6872                     else
6873                     {
6874                         bool ret;
6875                         ret = reservekey.GetReservedKey(pubKey);
6876                         assert(ret); // should never fail, as we just unlocked
6877                         changeDest = CTxDestination(pubKey);
6878                     }
6879                 }
6880
6881                 // generate all necessary change outputs for all currencies
6882                 // first determine if any outputs left are dust. if so, just add them to the fee
6883                 if (nChange < dustThreshold)
6884                 {
6885                     nFeeRet += nChange;
6886                     nChange = 0;
6887                 }
6888                 else
6889                 {
6890                     nChangePosRet = txNew.vout.size() - 1; // dont change first or last
6891                     nChangeOutputs++;
6892                     vector<CTxOut>::iterator position = txNew.vout.begin() + nChangePosRet;
6893                     txNew.vout.insert(position, CTxOut(nChange, GetScriptForDestination(changeDest)));
6894                 }
6895
6896                 // now, loop through the remaining reserve currencies and make a change output for each
6897                 // if dust, just remove
6898                 auto reserveIndexMap = currencyState.GetReserveMap();
6899                 for (auto &curChangeOut : reserveChange.valueMap)
6900                 {
6901                     CAmount outVal;
6902                     assert(curChangeOut.first != ASSETCHAINS_CHAINID);
6903                     auto curIt = reserveIndexMap.find(curChangeOut.first);
6904                     if (curIt != reserveIndexMap.end())
6905                     {
6906                         outVal = currencyState.ReserveToNative(curChangeOut.second, curIt->second);
6907                     }
6908                     else
6909                     {
6910                         outVal = curChangeOut.second;
6911                     }
6912                     
6913                     if (outVal >= dustThreshold)
6914                     {
6915                         vector<CTxOut>::iterator position = txNew.vout.begin() + (nChangePosRet + nChangeOutputs++);
6916                         CTokenOutput to = CTokenOutput(curChangeOut.first, curChangeOut.second);
6917                         txNew.vout.insert(position, CTxOut(0, MakeMofNCCScript(CConditionObj<CTokenOutput>(EVAL_RESERVE_OUTPUT, {changeDest}, 1, &to))));
6918                     }
6919                     // if it is dust and we cannot convert to native, drop it. it may be taken by the miner
6920                     else if (curIt != reserveIndexMap.end())
6921                     {
6922                         nFeeRet += outVal;
6923                     }
6924                 }
6925
6926                 // if we made no change outputs, return the key
6927                 if (!nChangeOutputs)
6928                 {
6929                     reservekey.ReturnKey();
6930                 }
6931             } else reservekey.ReturnKey();
6932
6933             // Fill vin
6934             //
6935             // Note how the sequence number is set to max()-1 so that the
6936             // nLockTime set above actually works.
6937             for (auto &oneIn : extraInputs)
6938             {
6939                 auto wit = mapWallet.find(oneIn.prevout.hash);
6940                 if (wit != mapWallet.end() &&
6941                     wit->second.vout.size() > oneIn.prevout.n &&
6942                     !wit->second.vout[oneIn.prevout.n].nValue &&
6943                     wit->second.vout[oneIn.prevout.n].ReserveOutValue() == CCurrencyValueMap())
6944                 {
6945                     setCoins.insert(std::make_pair(&(wit->second), oneIn.prevout.n));
6946                 }
6947                 else
6948                 {
6949                     setCoins.clear();
6950                     break;
6951                 }
6952             }
6953             BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6954                 txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
6955                                             std::numeric_limits<unsigned int>::max()-1));
6956
6957             // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
6958             size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
6959             {
6960                 LOCK(cs_main);
6961                 if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) {
6962                     limit = 0;
6963                 }
6964             }
6965             if (limit > 0) {
6966                 size_t n = txNew.vin.size();
6967                 if (n > limit) {
6968                     strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
6969                     return RPC_INVALID_PARAMETER;
6970                 }
6971             }
6972
6973             // Grab the current consensus branch ID
6974             auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
6975
6976             // Sign
6977             int nIn = 0;
6978             CTransaction txNewConst(txNew);
6979             BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6980             {
6981                 bool signSuccess;
6982                 const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
6983                 SignatureData sigdata;
6984                 if (sign)
6985                     signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, scriptPubKey), scriptPubKey, sigdata, consensusBranchId);
6986                 else
6987                     signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
6988
6989                 if (!signSuccess)
6990                 {
6991                     strFailReason = _("Signing transaction failed");
6992                     return RPC_TRANSACTION_ERROR;
6993                 } else {
6994                     UpdateTransaction(txNew, nIn, sigdata);
6995                 }
6996
6997                 nIn++;
6998             }
6999
7000             unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
7001
7002             // Remove scriptSigs if we used dummy signatures for fee calculation
7003             if (!sign) {
7004                 BOOST_FOREACH (CTxIn& vin, txNew.vin)
7005                     vin.scriptSig = CScript();
7006             }
7007
7008             // Embed the constructed transaction data in wtxNew.
7009             *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
7010
7011             // Limit size
7012             if (nBytes >= max_tx_size)
7013             {
7014                 strFailReason = _("Transaction too large");
7015                 return RPC_TRANSACTION_ERROR;
7016             }
7017
7018             dPriority = wtxNew.ComputePriority(dPriority, nBytes);
7019
7020             // Can we complete this as a free transaction?
7021             if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
7022             {
7023                 // Not enough fee: enough priority?
7024                 double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
7025                 // Not enough mempool history to estimate: use hard-coded AllowFree.
7026                 if (dPriorityNeeded <= 0 && AllowFree(dPriority))
7027                     break;
7028
7029                 // Small enough, and priority high enough, to send for free
7030                 if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
7031                     break;
7032             }
7033
7034             CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
7035             if ( nFeeNeeded < 5000 )
7036                 nFeeNeeded = 5000;
7037
7038             // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
7039             // because we must be at the maximum allowed fee.
7040             if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
7041             {
7042                 strFailReason = _("Transaction too large for fee policy");
7043                 return RPC_TRANSACTION_ERROR;
7044             }
7045
7046             if (nFeeRet >= nFeeNeeded)
7047                 break; // Done, enough fee included.
7048
7049             // Include more fee and try again.
7050             nFeeRet = nFeeNeeded;
7051             continue;
7052         }
7053     }
7054     return RPC_OK;
7055 }
7056
7057 /**
7058  * Call after CreateTransaction unless you want to abort
7059  */
7060 bool CWallet::CommitTransaction(CWalletTx& wtxNew, boost::optional<CReserveKey&> reservekey)
7061 {
7062     {
7063         LOCK2(cs_main, cs_wallet);
7064         LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
7065         {
7066             // This is only to keep the database open to defeat the auto-flush for the
7067             // duration of this scope.  This is the only place where this optimization
7068             // maybe makes sense; please don't do it anywhere else.
7069             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
7070
7071             if (reservekey) {
7072                 // Take key pair from key pool so it won't be used again
7073                 reservekey.get().KeepKey();
7074             }
7075
7076             // Add tx to wallet, because if it has change it's also ours,
7077             // otherwise just for transaction history.
7078             AddToWallet(wtxNew, false, pwalletdb);
7079
7080             // Notify that old coins are spent
7081             set<CWalletTx*> setCoins;
7082             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
7083             {
7084                 CWalletTx &coin = mapWallet[txin.prevout.hash];
7085                 coin.BindWallet(this);
7086                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
7087             }
7088
7089             if (fFileBacked)
7090                 delete pwalletdb;
7091         }
7092
7093         // Track how many getdata requests our transaction gets
7094         mapRequestCount[wtxNew.GetHash()] = 0;
7095
7096         if (fBroadcastTransactions)
7097         {
7098             // Broadcast
7099             if (!wtxNew.AcceptToMemoryPool(false))
7100             {
7101                 fprintf(stderr,"commit failed\n");
7102                 // This must not fail. The transaction has already been signed and recorded.
7103                 LogPrintf("CommitTransaction(): Error: Transaction not valid\n");
7104                 return false;
7105             }
7106             wtxNew.RelayWalletTransaction();
7107         }
7108     }
7109     return true;
7110 }
7111
7112 CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
7113 {
7114     // payTxFee is user-set "I want to pay this much"
7115     CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
7116     // user selected total at least (default=true)
7117     if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK())
7118         nFeeNeeded = payTxFee.GetFeePerK();
7119     // User didn't set: use -txconfirmtarget to estimate...
7120     if (nFeeNeeded == 0)
7121         nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
7122     // ... unless we don't have enough mempool data, in which case fall
7123     // back to a hard-coded fee
7124     if (nFeeNeeded == 0)
7125         nFeeNeeded = minTxFee.GetFee(nTxBytes);
7126     // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
7127     if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
7128         nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
7129     // But always obey the maximum
7130     if (nFeeNeeded > maxTxFee)
7131         nFeeNeeded = maxTxFee;
7132     return nFeeNeeded;
7133 }
7134
7135
7136 void komodo_prefetch(FILE *fp);
7137
7138 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
7139 {
7140     if (!fFileBacked)
7141         return DB_LOAD_OK;
7142     fFirstRunRet = false;
7143     if ( 0 ) // doesnt help
7144     {
7145         fprintf(stderr,"loading wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
7146         FILE *fp;
7147         if ( (fp= fopen(strWalletFile.c_str(),"rb")) != 0 )
7148         {
7149             komodo_prefetch(fp);
7150             fclose(fp);
7151         }
7152     }
7153     //fprintf(stderr,"prefetched wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
7154     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
7155     //fprintf(stderr,"loaded wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
7156     if (nLoadWalletRet == DB_NEED_REWRITE)
7157     {
7158         if (CDB::Rewrite(strWalletFile, "\x04pool"))
7159         {
7160             LOCK(cs_wallet);
7161             setKeyPool.clear();
7162             // Note: can't top-up keypool here, because wallet is locked.
7163             // User will be prompted to unlock wallet the next operation
7164             // that requires a new key.
7165         }
7166     }
7167
7168     if (nLoadWalletRet != DB_LOAD_OK)
7169         return nLoadWalletRet;
7170     fFirstRunRet = !vchDefaultKey.IsValid();
7171
7172     uiInterface.LoadWallet(this);
7173
7174     return DB_LOAD_OK;
7175 }
7176
7177
7178 DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
7179 {
7180     if (!fFileBacked)
7181         return DB_LOAD_OK;
7182     DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx);
7183     if (nZapWalletTxRet == DB_NEED_REWRITE)
7184     {
7185         if (CDB::Rewrite(strWalletFile, "\x04pool"))
7186         {
7187             LOCK(cs_wallet);
7188             setKeyPool.clear();
7189             // Note: can't top-up keypool here, because wallet is locked.
7190             // User will be prompted to unlock wallet the next operation
7191             // that requires a new key.
7192         }
7193     }
7194
7195     if (nZapWalletTxRet != DB_LOAD_OK)
7196         return nZapWalletTxRet;
7197
7198     return DB_LOAD_OK;
7199 }
7200
7201
7202 bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
7203 {
7204     bool fUpdated = false;
7205     {
7206         LOCK(cs_wallet); // mapAddressBook
7207         std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
7208         fUpdated = mi != mapAddressBook.end();
7209         mapAddressBook[address].name = strName;
7210         if (!strPurpose.empty()) /* update purpose only if requested */
7211             mapAddressBook[address].purpose = strPurpose;
7212     }
7213     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
7214                              strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
7215     if (!fFileBacked)
7216         return false;
7217     if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose))
7218         return false;
7219     return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName);
7220 }
7221
7222 bool CWallet::DelAddressBook(const CTxDestination& address)
7223 {
7224     {
7225         LOCK(cs_wallet); // mapAddressBook
7226
7227         if(fFileBacked)
7228         {
7229             // Delete destdata tuples associated with address
7230             std::string strAddress = EncodeDestination(address);
7231             BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
7232             {
7233                 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
7234             }
7235         }
7236         mapAddressBook.erase(address);
7237     }
7238
7239     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
7240
7241     if (!fFileBacked)
7242         return false;
7243     CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address));
7244     return CWalletDB(strWalletFile).EraseName(EncodeDestination(address));
7245 }
7246
7247 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
7248 {
7249     if (fFileBacked)
7250     {
7251         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
7252             return false;
7253     }
7254     vchDefaultKey = vchPubKey;
7255     return true;
7256 }
7257
7258 /**
7259  * Mark old keypool keys as used,
7260  * and generate all new keys
7261  */
7262 bool CWallet::NewKeyPool()
7263 {
7264     {
7265         LOCK(cs_wallet);
7266         CWalletDB walletdb(strWalletFile);
7267         BOOST_FOREACH(int64_t nIndex, setKeyPool)
7268             walletdb.ErasePool(nIndex);
7269         setKeyPool.clear();
7270
7271         if (IsLocked())
7272             return false;
7273
7274         int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
7275         for (int i = 0; i < nKeys; i++)
7276         {
7277             int64_t nIndex = i+1;
7278             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
7279             setKeyPool.insert(nIndex);
7280         }
7281         LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
7282     }
7283     return true;
7284 }
7285
7286 bool CWallet::TopUpKeyPool(unsigned int kpSize)
7287 {
7288     {
7289         LOCK(cs_wallet);
7290
7291         if (IsLocked())
7292             return false;
7293
7294         CWalletDB walletdb(strWalletFile);
7295
7296         // Top up key pool
7297         unsigned int nTargetSize;
7298         if (kpSize > 0)
7299             nTargetSize = kpSize;
7300         else
7301             nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
7302
7303         while (setKeyPool.size() < (nTargetSize + 1))
7304         {
7305             int64_t nEnd = 1;
7306             if (!setKeyPool.empty())
7307                 nEnd = *(--setKeyPool.end()) + 1;
7308             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
7309                 throw runtime_error("TopUpKeyPool(): writing generated key failed");
7310             setKeyPool.insert(nEnd);
7311             LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
7312         }
7313     }
7314     return true;
7315 }
7316
7317 void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
7318 {
7319     nIndex = -1;
7320     keypool.vchPubKey = CPubKey();
7321     {
7322         LOCK(cs_wallet);
7323
7324         if (!IsLocked())
7325             TopUpKeyPool();
7326
7327         // Get the oldest key
7328         if(setKeyPool.empty())
7329             return;
7330
7331         CWalletDB walletdb(strWalletFile);
7332
7333         nIndex = *(setKeyPool.begin());
7334         setKeyPool.erase(setKeyPool.begin());
7335         if (!walletdb.ReadPool(nIndex, keypool))
7336             throw runtime_error("ReserveKeyFromKeyPool(): read failed");
7337         if (!HaveKey(keypool.vchPubKey.GetID()))
7338             throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
7339         assert(keypool.vchPubKey.IsValid());
7340         //LogPrintf("keypool reserve %d\n", nIndex);
7341     }
7342 }
7343
7344 void CWallet::KeepKey(int64_t nIndex)
7345 {
7346     // Remove from key pool
7347     if (fFileBacked)
7348     {
7349         CWalletDB walletdb(strWalletFile);
7350         walletdb.ErasePool(nIndex);
7351     }
7352     LogPrintf("keypool keep %d\n", nIndex);
7353 }
7354
7355 void CWallet::ReturnKey(int64_t nIndex)
7356 {
7357     // Return to key pool
7358     {
7359         LOCK(cs_wallet);
7360         setKeyPool.insert(nIndex);
7361     }
7362     //LogPrintf("keypool return %d\n", nIndex);
7363 }
7364
7365 bool CWallet::GetKeyFromPool(CPubKey& result)
7366 {
7367     int64_t nIndex = 0;
7368     CKeyPool keypool;
7369     {
7370         LOCK(cs_wallet);
7371         ReserveKeyFromKeyPool(nIndex, keypool);
7372         if (nIndex == -1)
7373         {
7374             if (IsLocked()) return false;
7375             result = GenerateNewKey();
7376             return true;
7377         }
7378         KeepKey(nIndex);
7379         result = keypool.vchPubKey;
7380     }
7381     return true;
7382 }
7383
7384 int64_t CWallet::GetOldestKeyPoolTime()
7385 {
7386     int64_t nIndex = 0;
7387     CKeyPool keypool;
7388     ReserveKeyFromKeyPool(nIndex, keypool);
7389     if (nIndex == -1)
7390         return GetTime();
7391     ReturnKey(nIndex);
7392     return keypool.nTime;
7393 }
7394
7395 std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
7396 {
7397     map<CTxDestination, CAmount> balances;
7398
7399     {
7400         LOCK(cs_wallet);
7401         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
7402         {
7403             CWalletTx *pcoin = &walletEntry.second;
7404
7405             if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
7406                 continue;
7407
7408             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
7409                 continue;
7410
7411             int nDepth = pcoin->GetDepthInMainChain();
7412             if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
7413                 continue;
7414
7415             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
7416             {
7417                 CTxDestination addr;
7418                 if (!IsMine(pcoin->vout[i]))
7419                     continue;
7420                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
7421                     continue;
7422
7423                 CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
7424
7425                 if (!balances.count(addr))
7426                     balances[addr] = 0;
7427                 balances[addr] += n;
7428             }
7429         }
7430     }
7431
7432     return balances;
7433 }
7434
7435 set< set<CTxDestination> > CWallet::GetAddressGroupings()
7436 {
7437     AssertLockHeld(cs_wallet); // mapWallet
7438     set< set<CTxDestination> > groupings;
7439     set<CTxDestination> grouping;
7440
7441     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
7442     {
7443         CWalletTx *pcoin = &walletEntry.second;
7444
7445         if (pcoin->vin.size() > 0)
7446         {
7447             bool any_mine = false;
7448             // group all input addresses with each other
7449             BOOST_FOREACH(CTxIn txin, pcoin->vin)
7450             {
7451                 CTxDestination address;
7452                 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
7453                     continue;
7454                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
7455                     continue;
7456                 grouping.insert(address);
7457                 any_mine = true;
7458             }
7459
7460             // group change with input addresses
7461             if (any_mine)
7462             {
7463                BOOST_FOREACH(CTxOut txout, pcoin->vout)
7464                    if (IsChange(txout))
7465                    {
7466                        CTxDestination txoutAddr;
7467                        if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
7468                            continue;
7469                        grouping.insert(txoutAddr);
7470                    }
7471             }
7472             if (grouping.size() > 0)
7473             {
7474                 groupings.insert(grouping);
7475                 grouping.clear();
7476             }
7477         }
7478
7479         // group lone addrs by themselves
7480         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
7481             if (IsMine(pcoin->vout[i]))
7482             {
7483                 CTxDestination address;
7484                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
7485                     continue;
7486                 grouping.insert(address);
7487                 groupings.insert(grouping);
7488                 grouping.clear();
7489             }
7490     }
7491
7492     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
7493     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
7494     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
7495     {
7496         // make a set of all the groups hit by this new group
7497         set< set<CTxDestination>* > hits;
7498         map< CTxDestination, set<CTxDestination>* >::iterator it;
7499         BOOST_FOREACH(CTxDestination address, grouping)
7500             if ((it = setmap.find(address)) != setmap.end())
7501                 hits.insert((*it).second);
7502
7503         // merge all hit groups into a new single group and delete old groups
7504         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
7505         BOOST_FOREACH(set<CTxDestination>* hit, hits)
7506         {
7507             merged->insert(hit->begin(), hit->end());
7508             uniqueGroupings.erase(hit);
7509             delete hit;
7510         }
7511         uniqueGroupings.insert(merged);
7512
7513         // update setmap
7514         BOOST_FOREACH(CTxDestination element, *merged)
7515             setmap[element] = merged;
7516     }
7517
7518     set< set<CTxDestination> > ret;
7519     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
7520     {
7521         ret.insert(*uniqueGrouping);
7522         delete uniqueGrouping;
7523     }
7524
7525     return ret;
7526 }
7527
7528 std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
7529 {
7530     LOCK(cs_wallet);
7531     set<CTxDestination> result;
7532     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
7533     {
7534         const CTxDestination& address = item.first;
7535         const string& strName = item.second.name;
7536         if (strName == strAccount)
7537             result.insert(address);
7538     }
7539     return result;
7540 }
7541
7542 bool CReserveKey::GetReservedKey(CPubKey& pubkey)
7543 {
7544     if (nIndex == -1)
7545     {
7546         CKeyPool keypool;
7547         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
7548         if (nIndex != -1)
7549             vchPubKey = keypool.vchPubKey;
7550         else {
7551             return false;
7552         }
7553     }
7554     assert(vchPubKey.IsValid());
7555     pubkey = vchPubKey;
7556     return true;
7557 }
7558
7559 void CReserveKey::KeepKey()
7560 {
7561     if (nIndex != -1)
7562         pwallet->KeepKey(nIndex);
7563     nIndex = -1;
7564     vchPubKey = CPubKey();
7565 }
7566
7567 void CReserveKey::ReturnKey()
7568 {
7569     if (nIndex != -1)
7570         pwallet->ReturnKey(nIndex);
7571     nIndex = -1;
7572     vchPubKey = CPubKey();
7573 }
7574
7575 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
7576 {
7577     setAddress.clear();
7578
7579     CWalletDB walletdb(strWalletFile);
7580
7581     LOCK2(cs_main, cs_wallet);
7582     BOOST_FOREACH(const int64_t& id, setKeyPool)
7583     {
7584         CKeyPool keypool;
7585         if (!walletdb.ReadPool(id, keypool))
7586             throw runtime_error("GetAllReserveKeyHashes(): read failed");
7587         assert(keypool.vchPubKey.IsValid());
7588         CKeyID keyID = keypool.vchPubKey.GetID();
7589         if (!HaveKey(keyID))
7590             throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
7591         setAddress.insert(keyID);
7592     }
7593 }
7594
7595 void CWallet::UpdatedTransaction(const uint256 &hashTx)
7596 {
7597     {
7598         LOCK(cs_wallet);
7599         // Only notify UI if this transaction is in this wallet
7600         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
7601         if (mi != mapWallet.end())
7602             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
7603     }
7604 }
7605
7606 class MiningAddressScript : public CReserveScript
7607 {
7608     // CReserveScript requires implementing this function, so that if an
7609     // internal (not-visible) wallet address is used, the wallet can mark it as
7610     // important when a block is mined (so it then appears to the user).
7611     // If -mineraddress is set, the user already knows about and is managing the
7612     // address, so we don't need to do anything here.
7613     void KeepScript() {}
7614 };
7615
7616 void GetScriptForMiningAddress(boost::shared_ptr<CReserveScript> &script)
7617 {
7618     CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
7619     if (!IsValidDestination(addr)) {
7620         return;
7621     }
7622
7623     boost::shared_ptr<MiningAddressScript> mAddr(new MiningAddressScript());
7624     script = mAddr;
7625     script->reserveScript = GetScriptForDestination(addr);
7626 }
7627
7628 void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
7629 {
7630     if (!GetArg("-mineraddress", "").empty())
7631     {
7632         GetScriptForMiningAddress(script);
7633         return;
7634     }
7635
7636     boost::shared_ptr<CReserveKey> rKey(new CReserveKey(this));
7637     CPubKey pubkey;
7638     if (!rKey->GetReservedKey(pubkey))
7639         return;
7640
7641     script = rKey;
7642     script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
7643 }
7644
7645 void CWallet::LockCoin(COutPoint& output)
7646 {
7647     AssertLockHeld(cs_wallet); // setLockedCoins
7648     setLockedCoins.insert(output);
7649 }
7650
7651 void CWallet::UnlockCoin(COutPoint& output)
7652 {
7653     AssertLockHeld(cs_wallet); // setLockedCoins
7654     setLockedCoins.erase(output);
7655 }
7656
7657 void CWallet::UnlockAllCoins()
7658 {
7659     AssertLockHeld(cs_wallet); // setLockedCoins
7660     setLockedCoins.clear();
7661 }
7662
7663 bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
7664 {
7665     AssertLockHeld(cs_wallet); // setLockedCoins
7666     COutPoint outpt(hash, n);
7667
7668     return (setLockedCoins.count(outpt) > 0);
7669 }
7670
7671 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
7672 {
7673     AssertLockHeld(cs_wallet); // setLockedCoins
7674     for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
7675          it != setLockedCoins.end(); it++) {
7676         COutPoint outpt = (*it);
7677         vOutpts.push_back(outpt);
7678     }
7679 }
7680
7681
7682 // Note Locking Operations
7683
7684 void CWallet::LockNote(const JSOutPoint& output)
7685 {
7686     AssertLockHeld(cs_wallet); // setLockedSproutNotes
7687     setLockedSproutNotes.insert(output);
7688 }
7689
7690 void CWallet::UnlockNote(const JSOutPoint& output)
7691 {
7692     AssertLockHeld(cs_wallet); // setLockedSproutNotes
7693     setLockedSproutNotes.erase(output);
7694 }
7695
7696 void CWallet::UnlockAllSproutNotes()
7697 {
7698     AssertLockHeld(cs_wallet); // setLockedSproutNotes
7699     setLockedSproutNotes.clear();
7700 }
7701
7702 bool CWallet::IsLockedNote(const JSOutPoint& outpt) const
7703 {
7704     AssertLockHeld(cs_wallet); // setLockedSproutNotes
7705
7706     return (setLockedSproutNotes.count(outpt) > 0);
7707 }
7708
7709 std::vector<JSOutPoint> CWallet::ListLockedSproutNotes()
7710 {
7711     AssertLockHeld(cs_wallet); // setLockedSproutNotes
7712     std::vector<JSOutPoint> vOutpts(setLockedSproutNotes.begin(), setLockedSproutNotes.end());
7713     return vOutpts;
7714 }
7715
7716 void CWallet::LockNote(const SaplingOutPoint& output)
7717 {
7718     AssertLockHeld(cs_wallet);
7719     setLockedSaplingNotes.insert(output);
7720 }
7721
7722 void CWallet::UnlockNote(const SaplingOutPoint& output)
7723 {
7724     AssertLockHeld(cs_wallet);
7725     setLockedSaplingNotes.erase(output);
7726 }
7727
7728 void CWallet::UnlockAllSaplingNotes()
7729 {
7730     AssertLockHeld(cs_wallet);
7731     setLockedSaplingNotes.clear();
7732 }
7733
7734 bool CWallet::IsLockedNote(const SaplingOutPoint& output) const
7735 {
7736     AssertLockHeld(cs_wallet);
7737     return (setLockedSaplingNotes.count(output) > 0);
7738 }
7739
7740 std::vector<SaplingOutPoint> CWallet::ListLockedSaplingNotes()
7741 {
7742     AssertLockHeld(cs_wallet);
7743     std::vector<SaplingOutPoint> vOutputs(setLockedSaplingNotes.begin(), setLockedSaplingNotes.end());
7744     return vOutputs;
7745 }
7746
7747 /** @} */ // end of Actions
7748
7749 class CAffectedKeysVisitor : public boost::static_visitor<void> {
7750 private:
7751     const CKeyStore &keystore;
7752     std::vector<CKeyID> &vKeys;
7753
7754 public:
7755     CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
7756
7757     void Process(const CScript &script) {
7758         txnouttype type;
7759         std::vector<CTxDestination> vDest;
7760         int nRequired;
7761         if (ExtractDestinations(script, type, vDest, nRequired)) {
7762             BOOST_FOREACH(const CTxDestination &dest, vDest)
7763                 boost::apply_visitor(*this, dest);
7764         }
7765     }
7766
7767     void operator()(const CKeyID &keyId) {
7768         if (keystore.HaveKey(keyId))
7769             vKeys.push_back(keyId);
7770     }
7771
7772     void operator()(const CPubKey &key) {
7773         CKeyID keyId = key.GetID();
7774         if (keystore.HaveKey(keyId))
7775             vKeys.push_back(keyId);
7776     }
7777
7778     // TODO: need to finish storage of quantum public key in wallet
7779     void operator()(const CQuantumID &keyId) {
7780         if (keystore.HaveKey(keyId))
7781             vKeys.push_back(keyId);
7782     }
7783
7784     void operator()(const CIndexID &keyId) {
7785     }
7786
7787     void operator()(const CScriptID &scriptId) {
7788         CScript script;
7789         if (keystore.GetCScript(scriptId, script))
7790             Process(script);
7791     }
7792
7793     void operator()(const CIdentityID &idId) {
7794         std::pair<CIdentityMapKey, CIdentityMapValue> identity;
7795         if (keystore.GetIdentity(idId, identity))
7796         {
7797             for (auto dest : identity.second.primaryAddresses)
7798             {
7799                 boost::apply_visitor(*this, dest);
7800             }
7801         }
7802     }
7803
7804     void operator()(const CNoDestination &none) {}
7805 };
7806
7807 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
7808     AssertLockHeld(cs_wallet); // mapKeyMetadata
7809     mapKeyBirth.clear();
7810
7811     // get birth times for keys with metadata
7812     for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
7813         if (it->second.nCreateTime)
7814             mapKeyBirth[it->first] = it->second.nCreateTime;
7815
7816     // map in which we'll infer heights of other keys
7817     CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
7818     std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
7819     std::set<CKeyID> setKeys;
7820     GetKeys(setKeys);
7821     BOOST_FOREACH(const CKeyID &keyid, setKeys) {
7822         if (mapKeyBirth.count(keyid) == 0)
7823             mapKeyFirstBlock[keyid] = pindexMax;
7824     }
7825     setKeys.clear();
7826
7827     // if there are no such keys, we're done
7828     if (mapKeyFirstBlock.empty())
7829         return;
7830
7831     // find first block that affects those keys, if there are any left
7832     std::vector<CKeyID> vAffected;
7833     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
7834         // iterate over all wallet transactions...
7835         const CWalletTx &wtx = (*it).second;
7836         BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
7837         if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
7838             // ... which are already in a block
7839             int nHeight = blit->second->GetHeight();
7840             BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
7841                 // iterate over all their outputs
7842                 CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
7843                 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
7844                     // ... and all their affected keys
7845                     std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
7846                     if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->GetHeight())
7847                         rit->second = blit->second;
7848                 }
7849                 vAffected.clear();
7850             }
7851         }
7852     }
7853
7854     // Extract block timestamps for those keys
7855     for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
7856         mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
7857 }
7858
7859 bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
7860 {
7861     if (boost::get<CNoDestination>(&dest))
7862         return false;
7863
7864     mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
7865     if (!fFileBacked)
7866         return true;
7867     return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value);
7868 }
7869
7870 bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
7871 {
7872     if (!mapAddressBook[dest].destdata.erase(key))
7873         return false;
7874     if (!fFileBacked)
7875         return true;
7876     return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key);
7877 }
7878
7879 bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
7880 {
7881     mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
7882     return true;
7883 }
7884
7885 bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
7886 {
7887     std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
7888     if(i != mapAddressBook.end())
7889     {
7890         CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
7891         if(j != i->second.destdata.end())
7892         {
7893             if(value)
7894                 *value = j->second;
7895             return true;
7896         }
7897     }
7898     return false;
7899 }
7900
7901 CKeyPool::CKeyPool()
7902 {
7903     nTime = GetTime();
7904 }
7905
7906 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
7907 {
7908     nTime = GetTime();
7909     vchPubKey = vchPubKeyIn;
7910 }
7911
7912 CWalletKey::CWalletKey(int64_t nExpires)
7913 {
7914     nTimeCreated = (nExpires ? GetTime() : 0);
7915     nTimeExpires = nExpires;
7916 }
7917
7918 void CMerkleTx::SetMerkleBranch(const CBlock& block)
7919 {
7920     CBlock blockTmp;
7921
7922     // Update the tx's hashBlock
7923     hashBlock = block.GetHash();
7924
7925     // Locate the transaction
7926     for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
7927         if (block.vtx[nIndex] == *(CTransaction*)this)
7928             break;
7929     if (nIndex == (int)block.vtx.size())
7930     {
7931         vMerkleBranch.clear();
7932         nIndex = -1;
7933         LogPrintf("ERROR: %s: couldn't find tx (%s) in block (%s)\n", __func__, GetHash().GetHex().c_str(), hashBlock.GetHex().c_str());
7934     }
7935
7936     // Fill in merkle branch
7937     vMerkleBranch = block.GetMerkleBranch(nIndex);
7938 }
7939
7940 int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
7941 {
7942     if (hashBlock.IsNull() || nIndex == -1)
7943         return 0;
7944     AssertLockHeld(cs_main);
7945
7946     // Find the block it claims to be in
7947     BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
7948     if (mi == mapBlockIndex.end())
7949         return 0;
7950     CBlockIndex* pindex = (*mi).second;
7951     if (!pindex || !chainActive.Contains(pindex))
7952         return 0;
7953
7954     // Make sure the merkle branch connects to this block
7955     if (!fMerkleVerified)
7956     {
7957         if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
7958             return 0;
7959         fMerkleVerified = true;
7960     }
7961
7962     pindexRet = pindex;
7963     return chainActive.Height() - pindex->GetHeight() + 1;
7964 }
7965
7966 int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
7967 {
7968     AssertLockHeld(cs_main);
7969     int nResult = GetDepthInMainChainINTERNAL(pindexRet);
7970     if (nResult == 0 && !mempool.exists(GetHash()))
7971         return -1; // Not in chain, not in mempool
7972
7973     return nResult;
7974 }
7975
7976 int CMerkleTx::GetBlocksToMaturity() const
7977 {
7978     if ( ASSETCHAINS_SYMBOL[0] == 0 )
7979         COINBASE_MATURITY = _COINBASE_MATURITY;
7980     if (!IsCoinBase())
7981         return 0;
7982     int32_t depth = GetDepthInMainChain();
7983     int32_t ut = UnlockTime(0);
7984     int32_t toMaturity = (ut - chainActive.Height()) < 0 ? 0 : ut - chainActive.Height();
7985     //printf("depth.%i, unlockTime.%i, toMaturity.%i\n", depth, ut, toMaturity);
7986     ut = (COINBASE_MATURITY - depth) < 0 ? 0 : COINBASE_MATURITY - depth;
7987     return(ut < toMaturity ? toMaturity : ut);
7988 }
7989
7990 bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
7991 {
7992     CValidationState state;
7993     return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
7994 }
7995
7996 /**
7997  * Find notes in the wallet filtered by payment address, min depth and ability to spend.
7998  * These notes are decrypted and added to the output parameter vector, outEntries.
7999  */
8000 void CWallet::GetFilteredNotes(
8001     std::vector<SproutNoteEntry>& sproutEntries,
8002     std::vector<SaplingNoteEntry>& saplingEntries,
8003     std::string address,
8004     int minDepth,
8005     bool ignoreSpent,
8006     bool requireSpendingKey)
8007 {
8008     std::set<PaymentAddress> filterAddresses;
8009
8010     if (address.length() > 0) {
8011         filterAddresses.insert(DecodePaymentAddress(address));
8012     }
8013
8014     GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey);
8015 }
8016
8017 /**
8018  * Find notes in the wallet filtered by payment addresses, min depth, max depth, 
8019  * if the note is spent, if a spending key is required, and if the notes are locked.
8020  * These notes are decrypted and added to the output parameter vector, outEntries.
8021  */
8022 void CWallet::GetFilteredNotes(
8023     std::vector<SproutNoteEntry>& sproutEntries,
8024     std::vector<SaplingNoteEntry>& saplingEntries,
8025     std::set<PaymentAddress>& filterAddresses,
8026     int minDepth,
8027     int maxDepth,
8028     bool ignoreSpent,
8029     bool requireSpendingKey,
8030     bool ignoreLocked)
8031 {
8032     LOCK2(cs_main, cs_wallet);
8033
8034     for (auto & p : mapWallet) {
8035         CWalletTx wtx = p.second;
8036
8037         // Filter the transactions before checking for notes
8038         if (!CheckFinalTx(wtx) ||
8039             wtx.GetBlocksToMaturity() > 0 ||
8040             wtx.GetDepthInMainChain() < minDepth ||
8041             wtx.GetDepthInMainChain() > maxDepth) {
8042             continue;
8043         }
8044
8045         for (auto & pair : wtx.mapSproutNoteData) {
8046             JSOutPoint jsop = pair.first;
8047             SproutNoteData nd = pair.second;
8048             SproutPaymentAddress pa = nd.address;
8049
8050             // skip notes which belong to a different payment address in the wallet
8051             if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
8052                 continue;
8053             }
8054
8055             // skip note which has been spent
8056             if (ignoreSpent && nd.nullifier && IsSproutSpent(*nd.nullifier)) {
8057                 continue;
8058             }
8059
8060             // skip notes which cannot be spent
8061             if (requireSpendingKey && !HaveSproutSpendingKey(pa)) {
8062                 continue;
8063             }
8064
8065             // skip locked notes
8066             if (ignoreLocked && IsLockedNote(jsop)) {
8067                 continue;
8068             }
8069
8070             int i = jsop.js; // Index into CTransaction.vJoinSplit
8071             int j = jsop.n; // Index into JSDescription.ciphertexts
8072
8073             // Get cached decryptor
8074             ZCNoteDecryption decryptor;
8075             if (!GetNoteDecryptor(pa, decryptor)) {
8076                 // Note decryptors are created when the wallet is loaded, so it should always exist
8077                 throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa)));
8078             }
8079
8080             // determine amount of funds in the note
8081             auto hSig = wtx.vJoinSplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
8082             try {
8083                 SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
8084                         decryptor,
8085                         wtx.vJoinSplit[i].ciphertexts[j],
8086                         wtx.vJoinSplit[i].ephemeralKey,
8087                         hSig,
8088                         (unsigned char) j);
8089
8090                 sproutEntries.push_back(SproutNoteEntry {
8091                     jsop, pa, plaintext.note(pa), plaintext.memo(), wtx.GetDepthInMainChain() });
8092
8093             } catch (const note_decryption_failed &err) {
8094                 // Couldn't decrypt with this spending key
8095                 throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa)));
8096             } catch (const std::exception &exc) {
8097                 // Unexpected failure
8098                 throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
8099             }
8100         }
8101
8102         for (auto & pair : wtx.mapSaplingNoteData) {
8103             SaplingOutPoint op = pair.first;
8104             SaplingNoteData nd = pair.second;
8105
8106             auto maybe_pt = SaplingNotePlaintext::decrypt(
8107                 wtx.vShieldedOutput[op.n].encCiphertext,
8108                 nd.ivk,
8109                 wtx.vShieldedOutput[op.n].ephemeralKey,
8110                 wtx.vShieldedOutput[op.n].cm);
8111             assert(static_cast<bool>(maybe_pt));
8112             auto notePt = maybe_pt.get();
8113
8114             auto maybe_pa = nd.ivk.address(notePt.d);
8115             assert(static_cast<bool>(maybe_pa));
8116             auto pa = maybe_pa.get();
8117
8118             // skip notes which belong to a different payment address in the wallet
8119             if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
8120                 continue;
8121             }
8122
8123             if (ignoreSpent && nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
8124                 continue;
8125             }
8126
8127             // skip notes which cannot be spent
8128             if (requireSpendingKey) {
8129                 libzcash::SaplingIncomingViewingKey ivk;
8130                 libzcash::SaplingFullViewingKey fvk;
8131                 if (!(GetSaplingIncomingViewingKey(pa, ivk) &&
8132                     GetSaplingFullViewingKey(ivk, fvk) &&
8133                     HaveSaplingSpendingKey(fvk))) {
8134                     continue;
8135                 }
8136             }
8137
8138             // skip locked notes
8139             if (ignoreLocked && IsLockedNote(op)) {
8140                 continue;
8141             }
8142
8143             auto note = notePt.note(nd.ivk).get();
8144             saplingEntries.push_back(SaplingNoteEntry {
8145                 op, pa, note, notePt.memo(), wtx.GetDepthInMainChain() });
8146         }
8147     }
8148 }
8149
8150
8151 //
8152 // Shielded key and address generalizations
8153 //
8154
8155 bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const
8156 {
8157     return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr);
8158 }
8159
8160 bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
8161 {
8162     libzcash::SaplingIncomingViewingKey ivk;
8163
8164     // If we have a SaplingExtendedSpendingKey in the wallet, then we will
8165     // also have the corresponding SaplingFullViewingKey.
8166     return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
8167         m_wallet->HaveSaplingFullViewingKey(ivk);
8168 }
8169
8170 bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
8171 {
8172     return false;
8173 }
8174
8175 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const
8176 {
8177     return m_wallet->HaveSproutSpendingKey(zaddr);
8178 }
8179
8180 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
8181 {
8182     libzcash::SaplingIncomingViewingKey ivk;
8183     libzcash::SaplingFullViewingKey fvk;
8184
8185     return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
8186         m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
8187         m_wallet->HaveSaplingSpendingKey(fvk);
8188 }
8189
8190 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncoding& no) const
8191 {
8192     return false;
8193 }
8194
8195 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8196     const libzcash::SproutPaymentAddress &zaddr) const
8197 {
8198     libzcash::SproutSpendingKey k;
8199     if (m_wallet->GetSproutSpendingKey(zaddr, k)) {
8200         return libzcash::SpendingKey(k);
8201     } else {
8202         return boost::none;
8203     }
8204 }
8205
8206 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8207     const libzcash::SaplingPaymentAddress &zaddr) const
8208 {
8209     libzcash::SaplingExtendedSpendingKey extsk;
8210     if (m_wallet->GetSaplingExtendedSpendingKey(zaddr, extsk)) {
8211         return libzcash::SpendingKey(extsk);
8212     } else {
8213         return boost::none;
8214     }
8215 }
8216
8217 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8218     const libzcash::InvalidEncoding& no) const
8219 {
8220     // Defaults to InvalidEncoding
8221     return libzcash::SpendingKey();
8222 }
8223
8224 SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
8225     auto addr = sk.address();
8226     if (log){
8227         LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
8228     }
8229     if (m_wallet->HaveSproutSpendingKey(addr)) {
8230         return KeyAlreadyExists;
8231     } else if (m_wallet-> AddSproutZKey(sk)) {
8232         m_wallet->mapSproutZKeyMetadata[addr].nCreateTime = nTime;
8233         return KeyAdded;
8234     } else {
8235         return KeyNotAdded;
8236     }
8237 }
8238
8239 SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
8240     auto fvk = sk.expsk.full_viewing_key();
8241     auto ivk = fvk.in_viewing_key();
8242     auto addr = sk.DefaultAddress();
8243     {
8244         if (log){
8245             LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
8246         }
8247         // Don't throw error in case a key is already there
8248         if (m_wallet->HaveSaplingSpendingKey(fvk)) {
8249             return KeyAlreadyExists;
8250         } else {
8251             if (!m_wallet-> AddSaplingZKey(sk, addr)) {
8252                 return KeyNotAdded;
8253             }
8254
8255             // Sapling addresses can't have been used in transactions prior to activation.
8256             if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) {
8257                 m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime;
8258             } else {
8259                 // 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
8260                 m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
8261             }
8262             if (hdKeypath) {
8263                 m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
8264             }
8265             if (seedFpStr) {
8266                 uint256 seedFp;
8267                 seedFp.SetHex(seedFpStr.get());
8268                 m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
8269             }
8270             return KeyAdded;
8271         }    
8272     }
8273 }
8274
8275 SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const { 
8276     throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
8277 }
This page took 0.478089 seconds and 4 git commands to generate.