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 .
6 #include "wallet/wallet.h"
8 #include "asyncrpcqueue.h"
9 #include "checkpoints.h"
10 #include "coincontrol.h"
12 #include "consensus/upgrades.h"
13 #include "consensus/validation.h"
14 #include "consensus/consensus.h"
20 #include "rpc/protocol.h"
21 #include "rpc/server.h"
22 #include "script/script.h"
23 #include "script/sign.h"
25 #include "utilmoneystr.h"
26 #include "zcash/Note.hpp"
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"
37 #include <boost/algorithm/string/replace.hpp>
38 #include <boost/filesystem.hpp>
39 #include <boost/thread.hpp>
42 using namespace libzcash;
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"
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;
66 * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
67 * Override with -mintxfee
69 CFeeRate CWallet::minTxFee = CFeeRate(1000);
71 /** @defgroup mapWallet
76 struct CompareValueOnly
78 bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
79 const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
81 return t1.first < t2.first;
88 CCurrencyValueMap totalTargetValues;
90 CompareValueMap(const CCurrencyValueMap &targetValues) : totalTargetValues(targetValues) {}
91 bool CompareMaps(const CCurrencyValueMap &m1,
92 const CCurrencyValueMap &m2) const
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())
98 CCurrencyValueMap leftover1 = m1.SubtractToZero(totalTargetValues);
99 CCurrencyValueMap leftover2 = m2.SubtractToZero(totalTargetValues);
101 if (leftover1 < leftover2 && leftover2 < leftover1)
103 if (leftover1.valueMap.size() < leftover2.valueMap.size())
107 else if (leftover2.valueMap.size() < leftover1.valueMap.size())
112 return leftover1 < leftover2;
114 else if (m1 < m2 && m2 < m1)
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))
127 checkMap2 = checkMap1 - m2.IntersectingValues(m1);
129 for (auto &oneCur : checkMap2.valueMap)
131 total += oneCur.second;
146 std::string JSOutPoint::ToString() const
148 return strprintf("JSOutPoint(%s, %d, %d)", hash.ToString().substr(0,10), js, n);
151 std::string COutput::ToString() const
153 return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
156 const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
159 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
160 if (it == mapWallet.end())
162 return &(it->second);
165 // Generate a new spending key and return its public payment address
166 libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey()
168 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
170 auto k = SproutSpendingKey::random();
171 auto addr = k.address();
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");
177 // Create new metadata
178 int64_t nCreationTime = GetTime();
179 mapSproutZKeyMetadata[addr] = CKeyMetadata(nCreationTime);
181 if (!AddSproutZKey(k))
182 throw std::runtime_error("CWallet::GenerateNewSproutZKey(): AddSproutZKey failed");
186 // Generate a new Sapling spending key and return its public payment address
187 SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
189 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
191 // Create new metadata
192 int64_t nCreationTime = GetTime();
193 CKeyMetadata metadata(nCreationTime);
195 // Try to get the seed
197 if (!GetHDSeed(seed))
198 throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
200 auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
201 uint32_t bip44CoinType = Params().BIP44CoinType();
203 // We use a fixed keypath scheme of m/32'/coin_type'/account'
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);
209 // Derive account key at next index, skip keys already known to the wallet
210 libzcash::SaplingExtendedSpendingKey xsk;
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()));
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");
224 auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
225 mapSaplingZKeyMetadata[ivk] = metadata;
227 auto addr = xsk.DefaultAddress();
228 if (!AddSaplingZKey(xsk, addr)) {
229 throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
231 // return default sapling payment address.
235 // Add spending key to keystore
236 bool CWallet::AddSaplingZKey(
237 const libzcash::SaplingExtendedSpendingKey &sk,
238 const libzcash::SaplingPaymentAddress &defaultAddr)
240 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
242 if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
251 auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
252 return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
258 // Add payment address -> incoming viewing key map entry
259 bool CWallet::AddSaplingIncomingViewingKey(
260 const libzcash::SaplingIncomingViewingKey &ivk,
261 const libzcash::SaplingPaymentAddress &addr)
263 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
265 if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
274 return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
281 // Add spending key to keystore and persist to disk
282 bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key)
284 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
285 auto addr = key.address();
287 if (!CCryptoKeyStore::AddSproutSpendingKey(key))
290 // check if we need to remove from viewing keys
291 if (HaveSproutViewingKey(addr))
292 RemoveSproutViewingKey(key.viewing_key());
298 return CWalletDB(strWalletFile).WriteZKey(addr,
300 mapSproutZKeyMetadata[addr]);
305 CPubKey CWallet::GenerateNewKey()
307 AssertLockHeld(cs_wallet); // mapKeyMetadata
308 bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
311 secret.MakeNewKey(fCompressed);
313 // Compressed public keys were introduced in version 0.6.0
315 SetMinVersion(FEATURE_COMPRPUBKEY);
317 CPubKey pubkey = secret.GetPubKey();
318 assert(secret.VerifyPubKey(pubkey));
320 // Create new metadata
321 int64_t nCreationTime = GetTime();
322 mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
323 if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
324 nTimeFirstKey = nCreationTime;
326 if (!AddKeyPubKey(secret, pubkey))
327 throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
331 bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
333 AssertLockHeld(cs_wallet); // mapKeyMetadata
334 if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
337 // check if we need to remove from watch-only
339 script = GetScriptForDestination(pubkey.GetID());
340 if (HaveWatchOnly(script))
341 RemoveWatchOnly(script);
346 return CWalletDB(strWalletFile).WriteKey(pubkey,
348 mapKeyMetadata[pubkey.GetID()]);
353 bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
354 const vector<unsigned char> &vchCryptedSecret)
357 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
363 if (pwalletdbEncryption)
364 return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
366 mapKeyMetadata[vchPubKey.GetID()]);
368 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
370 mapKeyMetadata[vchPubKey.GetID()]);
376 bool CWallet::AddCryptedSproutSpendingKey(
377 const libzcash::SproutPaymentAddress &address,
378 const libzcash::ReceivingKey &rk,
379 const std::vector<unsigned char> &vchCryptedSecret)
381 if (!CCryptoKeyStore::AddCryptedSproutSpendingKey(address, rk, vchCryptedSecret))
387 if (pwalletdbEncryption) {
388 return pwalletdbEncryption->WriteCryptedZKey(address,
391 mapSproutZKeyMetadata[address]);
393 return CWalletDB(strWalletFile).WriteCryptedZKey(address,
396 mapSproutZKeyMetadata[address]);
402 bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
403 const std::vector<unsigned char> &vchCryptedSecret,
404 const libzcash::SaplingPaymentAddress &defaultAddr)
406 if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
412 if (pwalletdbEncryption) {
413 return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
415 mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
417 return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
419 mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
425 bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
427 AssertLockHeld(cs_wallet); // mapKeyMetadata
428 if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
429 nTimeFirstKey = meta.nCreateTime;
431 mapKeyMetadata[pubkey.GetID()] = meta;
435 bool CWallet::LoadZKeyMetadata(const SproutPaymentAddress &addr, const CKeyMetadata &meta)
437 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
438 mapSproutZKeyMetadata[addr] = meta;
442 bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
444 return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
447 bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret)
449 return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret);
452 bool CWallet::LoadCryptedSaplingZKey(
453 const libzcash::SaplingExtendedFullViewingKey &extfvk,
454 const std::vector<unsigned char> &vchCryptedSecret)
456 return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
459 bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
461 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
462 mapSaplingZKeyMetadata[ivk] = meta;
466 bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
468 return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
471 bool CWallet::LoadSaplingPaymentAddress(
472 const libzcash::SaplingPaymentAddress &addr,
473 const libzcash::SaplingIncomingViewingKey &ivk)
475 return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
478 bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
480 return CCryptoKeyStore::AddSproutSpendingKey(key);
483 bool CWallet::AddSproutViewingKey(const libzcash::SproutViewingKey &vk)
485 if (!CCryptoKeyStore::AddSproutViewingKey(vk)) {
488 nTimeFirstKey = 1; // No birthday information for viewing keys.
492 return CWalletDB(strWalletFile).WriteSproutViewingKey(vk);
495 bool CWallet::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk)
497 AssertLockHeld(cs_wallet);
498 if (!CCryptoKeyStore::RemoveSproutViewingKey(vk)) {
502 if (!CWalletDB(strWalletFile).EraseSproutViewingKey(vk)) {
510 bool CWallet::LoadSproutViewingKey(const libzcash::SproutViewingKey &vk)
512 return CCryptoKeyStore::AddSproutViewingKey(vk);
515 bool CWallet::AddCScript(const CScript& redeemScript)
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))
524 return CWalletDB(strWalletFile).WriteCScript(ScriptOrIdentityID(redeemScript), redeemScript);
527 bool CWallet::LoadCScript(const CScript& redeemScript)
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)
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);
540 return CCryptoKeyStore::AddCScript(redeemScript);
543 bool CWallet::AddIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
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))
552 return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
555 bool CWallet::UpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
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))
564 return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
567 bool CWallet::AddUpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
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))
576 return CWalletDB(strWalletFile).WriteIdentity(mapKey, identity);
579 void CWallet::ClearIdentities()
583 for (auto idPair : mapIdentities)
585 CWalletDB(strWalletFile).EraseIdentity(idPair.first);
589 CCryptoKeyStore::ClearIdentities();
592 bool CWallet::RemoveIdentity(const CIdentityMapKey &mapKey, const uint256 &txid)
594 CIdentityMapKey localKey = mapKey;
595 std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> toErase;
596 if (localKey.blockHeight == 0)
598 localKey.blockHeight = INT_MAX;
600 if (!GetIdentity(mapKey, localKey, toErase))
606 std::pair<CIdentityMapKey, CIdentityMapValue> idEntry;
607 for (auto id : toErase)
609 if (id.second.txid == txid)
615 if (idEntry.first.IsValid() && idEntry.second.IsValid())
617 toErase.push_back(idEntry);
620 if (!CCryptoKeyStore::RemoveIdentity(mapKey, txid))
626 for (auto idPair : toErase)
628 error = CWalletDB(strWalletFile).EraseIdentity(idPair.first) ? error : true;
633 bool CWallet::LoadIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
635 return CCryptoKeyStore::AddUpdateIdentity(mapKey, identity);
638 // returns all key IDs that are destinations for UTXOs in the wallet
639 std::set<CKeyID> CWallet::GetTransactionDestinationIDs()
641 std::vector<COutput> vecOutputs;
642 std::set<CKeyID> setKeyIDs;
644 AvailableCoins(vecOutputs, false, NULL, true, true, true, true);
646 for (int i = 0; i < vecOutputs.size(); i++)
648 auto &txout = vecOutputs[i];
650 std::vector<CTxDestination> dests;
653 if (ExtractDestinations(txout.tx->vout[txout.i].scriptPubKey, outType, dests, nRequiredSigs))
655 CScript scriptPubKey;
656 if (outType != TX_SCRIPTHASH ||
658 GetCScript(GetDestinationID(dests[0]), scriptPubKey) &&
659 ExtractDestinations(scriptPubKey, outType, dests, nRequiredSigs)))
661 for (auto &dest : dests)
663 if (dest.which() == COptCCParams::ADDRTYPE_PK || dest.which() == COptCCParams::ADDRTYPE_PKH)
665 setKeyIDs.insert(GetDestinationID(dest));
674 bool CWallet::AddWatchOnly(const CScript &dest)
676 if (!CCryptoKeyStore::AddWatchOnly(dest))
678 nTimeFirstKey = 1; // No birthday information for watch-only keys.
679 NotifyWatchonlyChanged(true);
682 return CWalletDB(strWalletFile).WriteWatchOnly(dest);
685 bool CWallet::RemoveWatchOnly(const CScript &dest)
687 AssertLockHeld(cs_wallet);
688 if (!CCryptoKeyStore::RemoveWatchOnly(dest))
690 if (!HaveWatchOnly())
691 NotifyWatchonlyChanged(false);
693 if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
699 bool CWallet::LoadWatchOnly(const CScript &dest)
701 return CCryptoKeyStore::AddWatchOnly(dest);
704 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
707 CKeyingMaterial vMasterKey;
711 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
713 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
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();
730 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
732 bool fWasLocked = IsLocked();
739 CKeyingMaterial vMasterKey;
740 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
742 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
744 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
746 if (CCryptoKeyStore::Unlock(vMasterKey))
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)));
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;
756 if (pMasterKey.second.nDeriveIterations < 25000)
757 pMasterKey.second.nDeriveIterations = 25000;
759 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
761 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
763 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
765 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
776 void CWallet::ChainTipAdded(const CBlockIndex *pindex,
777 const CBlock *pblock,
778 SproutMerkleTree sproutTree,
779 SaplingMerkleTree saplingTree)
781 IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree);
782 UpdateSaplingNullifierNoteMapForBlock(pblock);
785 void CWallet::ChainTip(const CBlockIndex *pindex,
786 const CBlock *pblock,
787 SproutMerkleTree sproutTree,
788 SaplingMerkleTree saplingTree,
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)
798 RunSaplingMigration(pindex->GetHeight());
801 DecrementNoteWitnesses(pindex);
802 UpdateSaplingNullifierNoteMapForBlock(pblock);
806 void CWallet::RunSaplingMigration(int blockHeight) {
807 if (!Params().GetConsensus().NetworkUpgradeActive(blockHeight, Consensus::UPGRADE_SAPLING)) {
811 if (!fSaplingMigrationEnabled) {
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
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();
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();
836 for (const CTransaction& transaction : pendingSaplingMigrationTxs) {
837 // Send the transaction
838 CWalletTx wtx(this, transaction);
839 CommitTransaction(wtx, boost::none);
841 pendingSaplingMigrationTxs.clear();
845 void CWallet::AddPendingSaplingMigrationTx(const CTransaction& tx) {
847 pendingSaplingMigrationTxs.push_back(tx);
850 void CWallet::SetBestChain(const CBlockLocator& loc)
852 CWalletDB walletdb(strWalletFile);
853 SetBestChainINTERNAL(walletdb, loc);
856 std::set<std::pair<libzcash::PaymentAddress, uint256>> CWallet::GetNullifiersForAddresses(
857 const std::set<libzcash::PaymentAddress> & addresses)
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);
871 for (const auto & txPair : mapWallet) {
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()));
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()));
896 bool CWallet::IsNoteSproutChange(
897 const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
898 const PaymentAddress & address,
899 const JSOutPoint & jsop)
901 // A Note is marked as "change" if the address that received it
902 // also spent Notes in the same transaction. This will catch,
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))) {
920 bool CWallet::IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
921 const libzcash::PaymentAddress & address,
922 const SaplingOutPoint & op)
924 // A Note is marked as "change" if the address that received it
925 // also spent Notes in the same transaction. This will catch,
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))) {
940 bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
942 LOCK(cs_wallet); // nWalletVersion
943 if (nWalletVersion >= nVersion)
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;
950 nWalletVersion = nVersion;
952 if (nVersion > nWalletMaxVersion)
953 nWalletMaxVersion = nVersion;
957 CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
958 if (nWalletVersion > 40000)
959 pwalletdb->WriteMinVersion(nWalletVersion);
967 bool CWallet::SetMaxVersion(int nVersion)
969 LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
970 // cannot downgrade below current version
971 if (nWalletVersion > nVersion)
974 nWalletMaxVersion = nVersion;
979 set<uint256> CWallet::GetConflicts(const uint256& txid) const
982 AssertLockHeld(cs_wallet);
984 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
985 if (it == mapWallet.end())
987 const CWalletTx& wtx = it->second;
989 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
991 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
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);
1000 std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
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
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);
1014 std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_o;
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
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);
1029 void CWallet::Flush(bool shutdown)
1031 bitdb.Flush(shutdown);
1034 bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
1036 if (!bitdb.Open(GetDataDir()))
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());
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)
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());
1057 if (GetBoolArg("-salvagewallet", false))
1059 // Recover readable keypairs:
1060 if (!CWalletDB::Recover(bitdb, walletFile, true))
1064 if (boost::filesystem::exists(GetDataDir() / walletFile))
1066 CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
1067 if (r == CDBEnv::RECOVER_OK)
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());
1074 if (r == CDBEnv::RECOVER_FAIL)
1075 errorString += _("wallet.dat corrupt, salvage failed");
1082 void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
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:
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)
1092 const uint256& hash = it->second;
1093 int n = mapWallet[hash].nOrderPos;
1094 if (n < nMinOrderPos)
1097 copyFrom = &mapWallet[hash];
1100 // Now copy data from copyFrom to rest:
1101 for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
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
1121 * Outpoint is spent if any non-conflicted transaction
1124 bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
1126 const COutPoint outpoint(hash, n);
1127 pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
1128 range = mapTxSpends.equal_range(outpoint);
1130 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
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
1141 * Note is spent if any non-conflicted transaction
1144 bool CWallet::IsSproutSpent(const uint256& nullifier) const {
1145 pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
1146 range = mapTxSproutNullifiers.equal_range(nullifier);
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
1158 bool CWallet::IsSaplingSpent(const uint256& nullifier) const {
1159 pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
1160 range = mapTxSaplingNullifiers.equal_range(nullifier);
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
1172 void CWallet::AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid)
1174 mapTxSpends.insert(make_pair(outpoint, wtxid));
1176 pair<TxSpends::iterator, TxSpends::iterator> range;
1177 range = mapTxSpends.equal_range(outpoint);
1178 SyncMetaData<COutPoint>(range);
1181 void CWallet::AddToSproutSpends(const uint256& nullifier, const uint256& wtxid)
1183 mapTxSproutNullifiers.insert(make_pair(nullifier, wtxid));
1185 pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
1186 range = mapTxSproutNullifiers.equal_range(nullifier);
1187 SyncMetaData<uint256>(range);
1190 void CWallet::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid)
1192 mapTxSaplingNullifiers.insert(make_pair(nullifier, wtxid));
1194 pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
1195 range = mapTxSaplingNullifiers.equal_range(nullifier);
1196 SyncMetaData<uint256>(range);
1199 void CWallet::AddToSpends(const uint256& wtxid)
1201 assert(mapWallet.count(wtxid));
1202 CWalletTx& thisTx = mapWallet[wtxid];
1203 if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
1206 for (const CTxIn& txin : thisTx.vin) {
1207 AddToTransparentSpends(txin.prevout, wtxid);
1209 for (const JSDescription& jsdesc : thisTx.vJoinSplit) {
1210 for (const uint256& nullifier : jsdesc.nullifiers) {
1211 AddToSproutSpends(nullifier, wtxid);
1214 for (const SpendDescription &spend : thisTx.vShieldedSpend) {
1215 AddToSaplingSpends(spend.nullifier, wtxid);
1219 void CWallet::ClearNoteWitnessCache()
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;
1227 for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
1228 item.second.witnesses.clear();
1229 item.second.witnessHeight = -1;
1232 nWitnessCacheSize = 0;
1233 //fprintf(stderr,"Clear witness cache\n");
1236 template<typename NoteDataMap>
1237 void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
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());
1256 if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
1257 nd->witnesses.pop_back();
1263 template<typename NoteDataMap>
1264 void AppendNoteCommitment(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment)
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);
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)
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(),
1294 nd->witnesses.front().root().GetHex(),
1296 witness.root().GetHex());
1297 nd->witnesses.clear();
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());
1308 template<typename NoteDataMap>
1309 void UpdateWitnessHeights(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
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());
1322 void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
1323 const CBlock* pblockIn,
1324 SproutMerkleTree& sproutTree,
1325 SaplingMerkleTree& saplingTree)
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);
1333 if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
1334 nWitnessCacheSize += 1;
1337 const CBlock* pblock {pblockIn};
1340 ReadBlockFromDisk(block, pindex, Params().GetConsensus());
1344 for (const CTransaction& tx : pblock->vtx) {
1345 auto hash = tx.GetHash();
1346 bool txIsOurs = mapWallet.count(hash);
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);
1354 // Increment existing witnesses
1355 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1356 ::AppendNoteCommitment(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
1359 // If this is our note, witness it
1361 JSOutPoint jsoutpt {hash, i, j};
1362 ::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, jsoutpt, sproutTree.witness());
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);
1371 // Increment existing witnesses
1372 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1373 ::AppendNoteCommitment(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
1376 // If this is our note, witness it
1378 SaplingOutPoint outPoint {hash, i};
1379 ::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, outPoint, saplingTree.witness());
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);
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).
1395 template<typename NoteDataMap>
1396 bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
1398 extern int32_t KOMODO_REWIND;
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)))
1413 printf("at height %d\n", indexHeight);
1416 if (nd->witnesses.size() > 0) {
1417 nd->witnesses.pop_front();
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;
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
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
1436 assert((nWitnessCacheSize - 1) >= nd->witnesses.size());
1439 assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0);
1443 void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
1446 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
1447 if (!::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize))
1449 if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize))
1452 if (nWitnessCacheSize != 0)
1454 nWitnessCacheSize -= 1;
1455 // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302)
1456 if (nWitnessCacheSize == 0)
1458 ClearNoteWitnessCache();
1460 //assert(nWitnessCacheSize > 0);
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).
1468 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
1473 CKeyingMaterial vMasterKey;
1475 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
1476 GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
1478 CMasterKey kMasterKey;
1480 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
1481 GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
1484 int64_t nStartTime = GetTimeMillis();
1485 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
1486 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
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;
1492 if (kMasterKey.nDeriveIterations < 25000)
1493 kMasterKey.nDeriveIterations = 25000;
1495 LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
1497 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
1499 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
1504 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
1507 assert(!pwalletdbEncryption);
1508 pwalletdbEncryption = new CWalletDB(strWalletFile);
1509 if (!pwalletdbEncryption->TxnBegin()) {
1510 delete pwalletdbEncryption;
1511 pwalletdbEncryption = NULL;
1514 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
1517 if (!EncryptKeys(vMasterKey))
1520 pwalletdbEncryption->TxnAbort();
1521 delete pwalletdbEncryption;
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.
1528 // Encryption was introduced in version 0.4.0
1529 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
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.
1540 delete pwalletdbEncryption;
1541 pwalletdbEncryption = NULL;
1545 Unlock(strWalletPassphrase);
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);
1554 NotifyStatusChanged(this);
1559 int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
1561 AssertLockHeld(cs_wallet); // nOrderPosNext
1562 int64_t nRet = nOrderPosNext++;
1564 pwalletdb->WriteOrderPosNext(nOrderPosNext);
1566 CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
1571 CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
1573 AssertLockHeld(cs_wallet); // mapWallet
1574 CWalletDB walletdb(strWalletFile);
1576 // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
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)
1583 CWalletTx* wtx = &((*it).second);
1584 txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
1587 walletdb.ListAccountCreditDebit(strAccount, acentries);
1588 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1590 txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
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
1602 arith_uint256 target;
1603 arith_uint256 curHash;
1604 COutput *pwinner = NULL;
1605 CWalletTx winnerWtx;
1607 txnouttype whichType;
1608 std:vector<std::vector<unsigned char>> vSolutions;
1610 pBlock->nNonce.SetPOSTarget(bnTarget, pBlock->nVersion);
1611 target.SetCompact(bnTarget);
1613 auto consensusParams = Params().GetConsensus();
1614 CValidationState state;
1616 std::vector<COutput> vecOutputs;
1617 std::vector<CWalletTx> vwtx;
1618 CAmount totalStakingAmount = 0;
1620 uint32_t solutionVersion = CConstVerusSolutionVector::GetVersionByHeight(nHeight);
1621 bool extendedStake = solutionVersion >= CActivationHeight::ACTIVATE_EXTENDEDSTAKE;
1624 LOCK2(cs_main, cs_wallet);
1625 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
1629 for (int i = 0; i < vecOutputs.size(); i++)
1631 auto &txout = vecOutputs[i];
1635 txout.i < txout.tx->vout.size() &&
1636 txout.tx->vout[txout.i].nValue > 0 &&
1638 (txout.nDepth >= VERUS_MIN_STAKEAGE) &&
1639 ((txout.tx->vout[txout.i].scriptPubKey.IsPayToCryptoCondition(p) &&
1642 txout.tx->vout[txout.i].scriptPubKey.IsSpendableOutputType(p)) ||
1644 Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) &&
1645 (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH))))
1647 totalStakingAmount += txout.tx->vout[txout.i].nValue;
1648 // if all are valid, no change, else compress
1651 vecOutputs[newSize] = txout;
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++)
1664 vwtx[i] = *vecOutputs[i].tx;
1665 vecOutputs[i].tx = &vwtx[i];
1670 if (totalStakingAmount)
1672 LogPrintf("Staking with %s VRSC\n", ValueFromAmount(totalStakingAmount).write().c_str());
1676 LogPrintf("No VRSC staking\n");
1680 // we get these sources of entropy to prove all sources in the header
1681 int posHeight = -1, powHeight = -1, altHeight = -1;
1685 pastHash = chainActive.GetVerusEntropyHash(nHeight, &posHeight, &powHeight, &altHeight);
1686 if (extendedStake && (altHeight == -1 && (powHeight == -1 || posHeight == -1)))
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);
1694 // secondBlockHeight is either less than first or -1 if there isn't one
1695 int secondBlockHeight = altHeight != -1 ?
1701 (posHeight > powHeight ?
1705 int proveBlockHeight = posHeight > secondBlockHeight ? posHeight : ((powHeight == -1) ? posHeight : powHeight);
1707 if (proveBlockHeight == -1)
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);
1717 CCoinsViewCache view(pcoinsTip);
1718 CMutableTransaction checkStakeTx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
1719 std::vector<CTxDestination> addressRet;
1722 BOOST_FOREACH(COutput &txout, vecOutputs)
1725 std::vector<CTxDestination> destinations;
1727 bool canSign = false, canSpend = false;
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) &&
1734 (!p.IsValid() && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) && ::IsMine(*this, destinations[0]))))
1736 uint256 txHash = txout.tx->GetHash();
1737 checkStakeTx.vin.push_back(CTxIn(COutPoint(txHash, txout.i)));
1739 LOCK2(cs_main, cs_wallet);
1741 if ((!pwinner || UintToArith256(curNonce) < UintToArith256(pBlock->nNonce)) &&
1742 !cheatList.IsUTXOInList(COutPoint(txHash, txout.i), nHeight <= 100 ? 1 : nHeight-100))
1744 if (view.HaveCoins(txHash) && Consensus::CheckTxInputs(checkStakeTx, state, view, nHeight, consensusParams))
1746 //printf("Found PoS block\nnNonce: %s\n", pBlock->nNonce.GetHex().c_str());
1748 curNonce = pBlock->nNonce;
1749 srcIndex = nHeight - txout.nDepth;
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");
1758 checkStakeTx.vin.pop_back();
1763 stakeSource = static_cast<CTransaction>(*pwinner->tx);
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());
1772 voutNum = pwinner->i;
1773 pBlock->nNonce = curNonce;
1775 if (solutionVersion >= CActivationHeight::ACTIVATE_STAKEHEADER)
1777 CDataStream headerStream = CDataStream(SER_NETWORK, PROTOCOL_VERSION);
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();
1794 // get map and MMR for stake source transaction
1795 CTransactionMap txMap(stakeSource);
1796 TransactionMMView txView(txMap.transactionMMR);
1797 uint256 txRoot = txView.GetRoot();
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);
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
1807 if (!ReadBlockFromDisk(block, chainActive[srcIndex], Params().GetConsensus(), false))
1809 LogPrintf("%s: ERROR: could not read block number %u from disk\n", __func__, srcIndex);
1813 BlockMMRange blockMMR(block.GetBlockMMRTree());
1814 BlockMMView blockView(blockMMR);
1817 for (txIndexPos = 0; txIndexPos < blockMMR.size(); txIndexPos++)
1819 uint256 txRootHashFromMMR = blockMMR[txIndexPos].hash;
1820 if (txRootHashFromMMR == txRoot)
1822 //printf("tx with root %s found in block\n", txRootHashFromMMR.GetHex().c_str());
1827 if (txIndexPos == blockMMR.size())
1829 LogPrintf("%s: ERROR: could not find source transaction root in block %u\n", __func__, srcIndex);
1833 // prove the tx up to the MMR root, which also contains the block hash
1834 CMMRProof txRootProof;
1835 if (!blockView.GetProof(txRootProof, txIndexPos))
1837 LogPrintf("%s: ERROR: could not create proof of source transaction in block %u\n", __func__, srcIndex);
1841 mmrView.resize(proveBlockHeight + 1);
1842 chainActive.GetMerkleProof(mmrView, txRootProof, srcIndex);
1844 headerStream << CPartialTransactionProof(txRootProof, txProofVec);
1846 CMMRProof blockHeaderProof1;
1847 if (!chainActive.GetBlockProof(mmrView, blockHeaderProof1, proveBlockHeight))
1849 LogPrintf("%s: ERROR: could not create block proof for block %u\n", __func__, srcIndex);
1852 headerStream << CBlockHeaderProof(blockHeaderProof1, chainActive[proveBlockHeight]->GetBlockHeader());
1854 CMMRProof blockHeaderProof2;
1855 if (!chainActive.GetBlockProof(mmrView, blockHeaderProof2, secondBlockHeight))
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
1861 headerStream << CBlockHeaderProof(blockHeaderProof2, chainActive[secondBlockHeight]->GetBlockHeader());
1863 std::vector<unsigned char> stx(headerStream.begin(), headerStream.end());
1865 // printf("\nFound Stake transaction... all proof serialized size == %lu\n", stx.size());
1867 CVerusSolutionVector(pBlock->nSolution).ResizeExtraData(stx.size());
1869 pBlock->SetExtraData(stx.data(), stx.size());
1871 //CBlockHeader blkHeader(*pBlock);
1872 //CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
1873 //printf("Staking block header size %ld\n", GetSerializeSize(s, blkHeader));
1881 int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, std::vector<unsigned char> &utxosig, CTxDestination &rewardDest) const
1883 CTransaction stakeSource;
1884 int32_t voutNum, siglen = 0;
1886 txnouttype whichType;
1887 std::vector<std::vector<unsigned char>> vSolutions;
1889 CBlockIndex *tipindex = chainActive.LastTip();
1890 uint32_t stakeHeight = tipindex->GetHeight() + 1;
1891 bool extendedStake = CConstVerusSolutionVector::GetVersionByHeight(stakeHeight) >= CActivationHeight::ACTIVATE_EXTENDEDSTAKE;
1893 bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
1895 if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, stakeHeight, bnTarget))
1897 //LogPrintf("Searched for eligible staking transactions, no winners found\n");
1902 SignatureData sigdata;
1904 auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
1906 const CKeyStore& keystore = *pwalletMain;
1907 txNew.vin.resize(1);
1908 txNew.vout.resize(1);
1910 txNew.vin[0].prevout.hash = stakeSource.GetHash();
1911 txNew.vin[0].prevout.n = voutNum;
1914 if (stakeSource.vout[voutNum].scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
1916 if (!p.vKeys.size())
1918 LogPrintf("%s: Please report - no destination on stake source\n");
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
1925 if (p.evalCode == EVAL_STAKEGUARD)
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));
1932 txNew.vout[0].scriptPubKey = stakeSource.vout[voutNum].scriptPubKey;
1934 rewardDest = p.vKeys[0];
1936 else if (Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
1938 if (whichType == TX_PUBKEY)
1940 txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG;
1941 rewardDest = CPubKey(vSolutions[0]);
1943 else if (whichType == TX_PUBKEYHASH)
1945 txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
1946 rewardDest = CKeyID(uint160(vSolutions[0]));
1950 LogPrintf("%s: Please report - found stake source that is not valid\n");
1959 // set expiry to time out after 100 blocks, so we can remove the transaction if it orphans
1960 txNew.nExpiryHeight = stakeHeight + 100;
1962 uint256 srcBlock = uint256();
1963 CBlockIndex *pSrcIndex;
1965 txNew.vout.push_back(CTxOut());
1966 CTxOut &txOut1 = txNew.vout[1];
1968 if (!GetTransaction(stakeSource.GetHash(), stakeSource, srcBlock))
1971 BlockMap::const_iterator it = mapBlockIndex.find(srcBlock);
1972 if (it == mapBlockIndex.end() || (pSrcIndex = it->second) == 0)
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();
1983 if (USE_EXTERNAL_PUBKEY)
1985 rewardDest = CPubKey(ParseHex(NOTARY_PUBKEY));
1987 else if (!VERUS_DEFAULTID.IsNull())
1989 rewardDest = VERUS_DEFAULTID;
1992 if (rewardDest.which() == COptCCParams::ADDRTYPE_INVALID)
1994 printf("%s: Invalid reward destinaton for stake\n", __func__);
1998 txOut1.scriptPubKey << OP_RETURN
1999 << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, tipindex->GetBlockHash(), rewardDest).AsVector();
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");
2011 // UpdateTransaction(cheat,0,cheatSig);
2012 // cheatList.Add(CTxHolder(CTransaction(cheat), tipindex->GetHeight() + 1));
2016 nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
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);
2023 fprintf(stderr,"failed to create signature\n");
2029 UpdateTransaction(txNew, 0, sigdata);
2030 utxosig.resize(sigdata.scriptSig.size());
2031 memcpy(&(utxosig[0]), &(sigdata.scriptSig[0]), utxosig.size());
2033 return(utxosig.size());
2036 void CWallet::MarkDirty()
2040 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
2041 item.second.MarkDirty();
2046 * Ensure that every note in the wallet (for which we possess a spending key)
2047 * has a cached nullifier.
2049 bool CWallet::UpdateNullifierNoteMap()
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,
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
2078 UpdateNullifierNoteMapWithTx(wtxItem.second);
2085 * Update mapSproutNullifiersToNotes and mapSaplingNullifiersToNotes
2086 * with the cached nullifiers in this tx.
2088 void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
2092 for (const mapSproutNoteData_t::value_type& item : wtx.mapSproutNoteData) {
2093 if (item.second.nullifier) {
2094 mapSproutNullifiersToNotes[*item.second.nullifier] = item.first;
2098 for (const mapSaplingNoteData_t::value_type& item : wtx.mapSaplingNoteData) {
2099 if (item.second.nullifier) {
2100 mapSaplingNullifiersToNotes[*item.second.nullifier] = item.first;
2107 * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
2109 void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
2112 for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
2113 SaplingOutPoint op = item.first;
2114 SaplingNoteData nd = item.second;
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());
2121 item.second.nullifier = boost::none;
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.
2133 auto optNote = optPlaintext.get().note(nd.ivk);
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?
2142 uint256 nullifier = optNullifier.get();
2143 mapSaplingNullifiersToNotes[nullifier] = op;
2144 item.second.nullifier = nullifier;
2150 * Iterate over transactions in a block and update the cached Sapling nullifiers
2151 * for transactions which belong to the wallet.
2153 void CWallet::UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock) {
2156 for (const CTransaction& tx : pblock->vtx) {
2157 auto hash = tx.GetHash();
2158 bool txIsOurs = mapWallet.count(hash);
2160 UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]);
2165 bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
2167 uint256 hash = wtxIn.GetHash();
2169 if (fFromLoadWallet)
2171 mapWallet[hash] = wtxIn;
2172 mapWallet[hash].BindWallet(this);
2173 UpdateNullifierNoteMapWithTx(mapWallet[hash]);
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;
2187 wtx.nTimeReceived = GetAdjustedTime();
2188 wtx.nOrderPos = IncOrderPosNext(pwalletdb);
2190 wtx.nTimeSmart = wtx.nTimeReceived;
2191 if (!wtxIn.hashBlock.IsNull())
2193 if (mapBlockIndex.count(wtxIn.hashBlock))
2195 int64_t latestNow = wtx.nTimeReceived;
2196 int64_t latestEntry = 0;
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)
2204 CWalletTx *const pwtx = (*it).second.first;
2207 CAccountingEntry *const pacentry = (*it).second.second;
2211 nSmartTime = pwtx->nTimeSmart;
2213 nSmartTime = pwtx->nTimeReceived;
2216 nSmartTime = pacentry->nTime;
2217 if (nSmartTime <= latestTolerated)
2219 latestEntry = nSmartTime;
2220 if (nSmartTime > latestNow)
2221 latestNow = nSmartTime;
2227 int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
2228 wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2231 LogPrintf("AddToWallet(): found %s in block %s not in index\n",
2232 wtxIn.GetHash().ToString(),
2233 wtxIn.hashBlock.ToString());
2238 bool fUpdated = false;
2242 if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
2244 wtx.hashBlock = wtxIn.hashBlock;
2247 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
2249 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
2250 wtx.nIndex = wtxIn.nIndex;
2253 if (UpdatedNoteData(wtxIn, wtx)) {
2256 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
2258 wtx.fFromMe = wtxIn.fFromMe;
2266 LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
2270 if (fInsertedNew || fUpdated)
2271 if (!wtx.WriteToDisk(pwalletdb))
2274 // Break debit/credit balance caches:
2277 // Notify UI of new or updated transaction
2278 NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
2280 // notify an external script when a wallet transaction comes in or is updated
2281 std::string strCmd = GetArg("-walletnotify", "");
2283 if ( !strCmd.empty())
2285 boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
2286 boost::thread t(runCommand, strCmd); // thread runs free
2293 bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
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());
2304 tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
2306 // Now copy over the updated note data
2307 wtx.mapSproutNoteData = tmp;
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
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());
2320 tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
2323 // Now copy over the updated note data
2324 wtx.mapSaplingNoteData = tmp;
2327 return !unchangedSproutFlag || !unchangedSaplingFlag;
2330 std::pair<bool, bool> CWallet::CheckAuthority(const CIdentity &identity)
2332 std::pair<bool, bool> canSignCanSpend({false, false});
2333 if (!identity.IsValidUnrevoked())
2335 return canSignCanSpend;
2337 std::set<CIdentityID> keySet;
2339 // determine our status of cansign or canspend for this new ID
2340 for (auto key : identity.primaryAddresses)
2342 CKeyID keyID = CKeyID(GetDestinationID(key));
2345 keySet.insert(keyID);
2349 // if we have enough keys to fully authorize, it is ours
2350 if (keySet.size() >= identity.minSigs)
2352 canSignCanSpend.first = true;
2353 canSignCanSpend.second = true;
2355 else if (keySet.size())
2357 canSignCanSpend.first = true;
2359 return canSignCanSpend;
2362 bool CWallet::MarkIdentityDirty(const CIdentityID &idID)
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)
2371 std::vector<CTxDestination> addresses;
2373 for (auto txout : txidAndWtx.second.vout)
2375 if (txout.scriptPubKey.IsPayToCryptoCondition() && ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs))
2377 for (auto dest : addresses)
2379 if (GetDestinationID(dest) == idID)
2390 txidAndWtx.second.MarkDirty();
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.
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().
2408 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
2411 AssertLockHeld(cs_wallet);
2412 AssertLockHeld(cs_main);
2413 uint256 txHash = tx.GetHash();
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)) {
2427 uint32_t nHeight = 0;
2430 auto blkIndexIt = mapBlockIndex.find(pblock->GetHash());
2431 if (blkIndexIt != mapBlockIndex.end())
2433 nHeight = blkIndexIt->second->GetHeight();
2437 // this should never happen
2442 for (auto output : tx.vout)
2444 bool canSpend = false;
2447 if (output.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.version >= p.VERSION_V3)
2449 CIdentityMapValue identity;
2451 if (p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size() && (*(CIdentity *)&identity = CIdentity(p.vData[0])).IsValid())
2453 identity.txid = txHash;
2454 CIdentityMapKey idMapKey = CIdentityMapKey(identity.GetID(),
2457 CIdentityMapKey::VALID);
2459 std::set<CKeyID> keySet;
2460 CIdentityID idID(identity.GetID());
2462 bool doneWithID = false;
2464 std::pair<CIdentityMapKey, CIdentityMapValue> idHistory;
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));
2471 // if the new identity is revoked, the recovery identity holds can sign/can spend authority
2472 if (identity.IsRevoked())
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))
2479 canSignCanSpend = CheckAuthority(recoveryAuthority.second);
2483 // does identity already exist in this wallet?
2484 if (GetIdentity(idID, idHistory, nHeight ? nHeight : INT_MAX))
2486 wasCanSignCanSpend = CheckAuthority(idHistory.second);
2488 if (idHistory.second.IsRevoked())
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))
2497 auxCSCS = CheckAuthority(oldRecoveryAuthority.second);
2498 wasCanSignCanSpend = std::pair<bool, bool>({wasCanSignCanSpend.first || auxCSCS.first,
2499 wasCanSignCanSpend.second || auxCSCS.second});
2503 // if this is an add of the initial registration, delete all other instances of the ID
2504 if (CNameReservation(tx).IsValid())
2506 while (GetIdentity(idID, idHistory))
2508 // any definition of this identity in this wallet must be
2510 RemoveIdentity(idHistory.first, idHistory.second.txid);
2511 if (idHistory.second.txid != txHash)
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);
2517 // set wasCanSignCanSpend to true, true to delete any dependent transactions
2518 wasCanSignCanSpend = {true, true};
2520 idHistory = std::pair<CIdentityMapKey, CIdentityMapValue>();
2521 wasCanSignCanSpend = std::pair<bool, bool>({false, false});
2523 else if (nHeight && idHistory.first.blockHeight == nHeight && idHistory.second.txid != identity.txid)
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);
2530 std::map<uint256, std::pair<CIdentityMapKey, CIdentityMapValue>> firstIDMap;
2531 for (auto &foundID : thisHeightIdentities)
2533 firstIDMap[foundID.second.txid] = foundID;
2536 if (firstIDMap.count(identity.txid))
2542 blockOrder = thisHeightIdentities.size() + 1;
2543 firstIDMap.insert(make_pair(identity.txid,
2544 make_pair(CIdentityMapKey(idID,
2547 (canSignCanSpend.first ? CIdentityMapKey::CAN_SIGN : 0) + canSignCanSpend.second ? CIdentityMapKey::CAN_SPEND : 0),
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;
2556 for (auto &idEntry : firstIDMap)
2559 CTransaction entryTx;
2561 if (!myGetTransaction(idEntry.first, entryTx, blkHash))
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());
2567 bool isFirst = true;
2568 for (auto &input : entryTx.vin)
2570 auto idMapIt = firstIDMap.find(input.prevout.hash);
2571 if (idMapIt != firstIDMap.end())
2573 indexedByPrior[input.prevout.hash] = idEntry.second;
2579 // this should first be added solo, so #1 should always be set
2580 if (idEntry.second.first.blockOrder != 1)
2582 LogPrint("%s - error: unexpected block order in %s\n", __func__, idEntry.first.GetHex().c_str());
2584 firstInBlock = idEntry.second;
2589 if (!firstInBlock.first.IsValid())
2591 LogPrint("%s - error: missing first in block\n", __func__);
2595 // now validate that from 1st to last, we have order correct
2596 std::pair<CIdentityMapKey, CIdentityMapValue> *pCurID;
2598 for (pCurID = &firstInBlock; pCurID; i++)
2600 if (pCurID->first.blockOrder != i)
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());
2609 else if (nHeight && idHistory.first.blockHeight == nHeight)
2611 // nHeight means this is an add, it has the same txid as an ID already present in the wallet, so we can ignore
2616 if (idHistory.first.flags & idHistory.first.CAN_SPEND)
2618 wasCanSignCanSpend.first = true;
2619 wasCanSignCanSpend.second = true;
2621 else if ((idHistory.first.flags & idHistory.first.CAN_SIGN))
2623 wasCanSignCanSpend.first = true;
2625 // if we are supposed to remove the last entry, do so
2626 if (!pblock && txHash == idHistory.second.txid)
2628 RemoveIdentity(idHistory.first, idHistory.second.txid);
2634 // not present, nothing to delete
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))
2645 idMapKey = CIdentityMapKey(identity.GetID(),
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);
2657 std::pair<bool, bool> swapBools = canSignCanSpend;
2658 canSignCanSpend = wasCanSignCanSpend;
2659 wasCanSignCanSpend = swapBools;
2662 // store transitions as needed in the wallet
2663 if (canSignCanSpend.first != wasCanSignCanSpend.first || canSignCanSpend.second != wasCanSignCanSpend.second)
2665 // mark all transactions dirty to recalculate numbers
2666 for (auto &txidAndWtx : mapWallet)
2668 // mark the whole wallet dirty. if this is an issue, we can optimize.
2669 txidAndWtx.second.MarkDirty();
2672 if (canSignCanSpend.first != wasCanSignCanSpend.first)
2674 if (canSignCanSpend.first)
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);
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)
2688 unspentTxSet.insert(newOut.first.txhash);
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)
2695 // if it's not in the chain, or already in the unspent set to check, we don't need to add it to
2697 if (!wtx.second.IsInMainChain() ||
2698 unspentTxSet.count(wtx.first))
2702 int unspentOutputsSize = unspentOutputs.size();
2703 for (int k = 0; k < wtx.second.vout.size(); k++)
2705 const CTxOut &oneOut = wtx.second.vout[k];
2706 txnouttype newTypeRet;
2707 std::vector<CTxDestination> newAddressRet;
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))
2717 for (auto &oneDest : newAddressRet)
2719 if (oneDest.which() == COptCCParams::ADDRTYPE_ID && GetDestinationID(oneDest) == idID)
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
2729 // we only need to add one output to check all outputs below
2730 if (unspentOutputsSize < unspentOutputs.size())
2735 if (unspentOutputsSize < unspentOutputs.size())
2741 auto consensus = Params().GetConsensus();
2742 for (auto &newOut : unspentOutputs)
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);
2748 txnouttype newTypeRet;
2749 std::vector<CTxDestination> newAddressRet;
2751 bool newCanSign, newCanSpend;
2752 const CWalletTx *pWtx = GetWalletTx(newOut.first.txhash);
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())
2758 if (!(ExtractDestinations(newOut.second.script, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
2764 if (myGetTransaction(newOut.first.txhash, newTx, blkHash))
2766 wtx = CWalletTx(this, newTx);
2768 // Get merkle branch if transaction was found in a block
2770 auto blkIndexIt = mapBlockIndex.find(blkHash);
2771 if (!blkHash.IsNull() && blkIndexIt != mapBlockIndex.end() && chainActive.Contains(blkIndexIt->second))
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))
2778 wtx.SetMerkleBranch(block);
2781 AddToWallet(wtx, false, &walletdb);
2782 pWtx = GetWalletTx(newOut.first.txhash);
2785 else if (pWtx = GetWalletTx(newOut.first.txhash))
2787 if (!(ExtractDestinations(newOut.second.script, newTypeRet, newAddressRet, newNRequired, this, &newCanSign, &newCanSpend, nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
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())
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++)
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)
2811 // if we can't spend it, no need to check for spends
2812 if (!(ExtractDestinations(checkIfSpent[i].scriptPubKey,
2819 nHeight == 0 ? INT_MAX : nHeight + 1) && newCanSign))
2824 CSpentIndexValue spentInfo;
2825 CSpentIndexKey spentKey(newOut.first.txhash, i);
2826 if (GetSpentIndex(spentKey, spentInfo))
2828 if (GetWalletTx(spentInfo.txid) == nullptr &&
2829 spentInfo.blockHeight <= nHeight &&
2830 myGetTransaction(spentInfo.txid, spendTx, spendBlkHash) && !spendBlkHash.IsNull())
2832 CWalletTx spendWtx(this, spendTx);
2834 // Get merkle branch if transaction was found in a block
2836 auto spendBlkIndexIt = mapBlockIndex.find(spendBlkHash);
2837 if (spendBlkIndexIt != mapBlockIndex.end() &&
2838 chainActive.Contains(spendBlkIndexIt->second) &&
2839 ReadBlockFromDisk(spendBlock, spendBlkIndexIt->second, consensus))
2841 spendWtx.SetMerkleBranch(spendBlock);
2842 AddToWallet(spendWtx, false, &walletdb);
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());
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
2863 std::set<CIdentityID> idsToCheck = std::set<CIdentityID>();
2867 idsToCheck.insert(idID);
2870 // first and last blocks to consider when deleting spent transactions from the wallet
2871 uint32_t deleteSpentFrom;
2875 deleteSpentFrom = idHistory.first.blockHeight + 1;
2879 deleteSpentFrom = idMapKey.blockHeight + 1;
2882 std::map<const uint256 *, CWalletTx *> txesToErase;
2884 for (auto &txidAndWtx : mapWallet)
2886 const CBlockIndex *pIndex;
2887 if (txidAndWtx.second.GetDepthInMainChain(pIndex) > 0 && pIndex->GetHeight() <= deleteSpentFrom)
2893 std::vector<CTxDestination> addresses;
2895 bool eraseTx = true;
2897 uint256 hashTx = txidAndWtx.second.GetHash();
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())
2904 // don't erase the tx, but check to erase IDs
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))
2915 // look for a reason not to delete this tx or IDs it is sent to
2916 for (auto txout : txidAndWtx.second.vout)
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))
2921 // if this is ours, we will not erase the tx
2922 // we already checked IsFromMe
2929 bool canSignOut = false;
2930 bool canSpendOut = false;
2932 if (ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs, this, &canSignOut, &canSpendOut, nHeight == 0 ? INT_MAX : nHeight + 1))
2934 if (canSignOut || canSpendOut)
2936 // we should keep this transaction anyhow, check next
2941 for (auto &dest : addresses)
2943 if (dest.which() == COptCCParams::ADDRTYPE_ID)
2945 idsToCheck.insert(GetDestinationID(dest));
2954 txesToErase.insert(make_pair(&txidAndWtx.first, &txidAndWtx.second));
2958 for (auto &oneTx : txesToErase)
2960 EraseFromWallet(*oneTx.first);
2963 if (pblock && idsToCheck.count(idID))
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);
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)
2976 for (auto txout : txidAndWtx.second.vout)
2978 if (!txout.scriptPubKey.IsPayToCryptoCondition())
2982 bool canSignOut = false;
2983 bool canSpendOut = false;
2985 std::vector<CTxDestination> addresses;
2987 if (ExtractDestinations(txout.scriptPubKey, txType, addresses, minSigs, this, &canSignOut, &canSpendOut, nHeight == 0 ? INT_MAX : nHeight + 1))
2989 if (canSignOut || canSpendOut)
2991 for (auto &dest : addresses)
2993 if (dest.which() == COptCCParams::ADDRTYPE_ID)
2995 idsToCheck.erase(GetDestinationID(dest));
2996 if (!idsToCheck.size())
3004 if (!idsToCheck.size())
3009 if (!idsToCheck.size())
3015 // delete all remaining IDs that are not held for manual hold
3016 for (auto &idToRemove : idsToCheck)
3018 std::pair<CIdentityMapKey, CIdentityMapValue> identityToRemove;
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))
3025 std::pair<CIdentityMapKey, CIdentityMapValue> priorIdentity;
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))
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))
3034 RemoveIdentity(CIdentityMapKey(idToRemove));
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)
3051 CWalletTx wtx(this, tx);
3053 if (sproutNoteData.size() > 0) {
3054 wtx.SetSproutNoteData(sproutNoteData);
3057 if (saplingNoteData.size() > 0) {
3058 wtx.SetSaplingNoteData(saplingNoteData);
3061 // Get merkle branch if transaction was found in a block
3063 wtx.SetMerkleBranch(*pblock);
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);
3069 return AddToWallet(wtx, false, &walletdb);
3075 void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
3078 if (!AddToWalletIfInvolvingMe(tx, pblock, true))
3079 return; // Not one of ours
3081 MarkAffectedTransactionsDirty(tx);
3084 void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx)
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)
3091 if (mapWallet.count(txin.prevout.hash))
3092 mapWallet[txin.prevout.hash].MarkDirty();
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();
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();
3112 void CWallet::EraseFromWallet(const uint256 &hash)
3118 if (mapWallet.erase(hash))
3119 CWalletDB(strWalletFile).EraseTx(hash);
3124 void CWallet::RescanWallet()
3128 CBlockIndex *start = chainActive.Height() > 0 ? chainActive[1] : NULL;
3130 ScanForWalletTransactions(start, true);
3131 needsRescan = false;
3137 * Returns a nullifier if the SpendingKey is available
3138 * Throws std::runtime_error if the decryptor doesn't match this note
3140 boost::optional<uint256> CWallet::GetSproutNoteNullifier(const JSDescription &jsdesc,
3141 const libzcash::SproutPaymentAddress &address,
3142 const ZCNoteDecryption &dec,
3143 const uint256 &hSig,
3146 boost::optional<uint256> ret;
3147 auto note_pt = libzcash::SproutNotePlaintext::decrypt(
3149 jsdesc.ciphertexts[n],
3150 jsdesc.ephemeralKey,
3153 auto note = note_pt.note(address);
3155 // Check note plaintext against note commitment
3156 if (note.cm() != jsdesc.commitments[n]) {
3157 throw libzcash::note_decryption_failed();
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);
3171 * Finds all output notes in the given transaction that have been sent to
3172 * PaymentAddresses in this wallet.
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.
3178 mapSproutNoteData_t CWallet::FindMySproutNotes(const CTransaction &tx) const
3180 LOCK(cs_SpendingKeyStore);
3181 uint256 hash = tx.GetHash();
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) {
3189 auto address = item.first;
3190 JSOutPoint jsoutpt {hash, i, j};
3191 auto nullifier = GetSproutNoteNullifier(
3197 SproutNoteData nd {address, *nullifier};
3198 noteData.insert(std::make_pair(jsoutpt, nd));
3200 SproutNoteData nd {address};
3201 noteData.insert(std::make_pair(jsoutpt, nd));
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());
3219 * Finds all output notes in the given transaction that have been sent to
3220 * SaplingPaymentAddresses in this wallet.
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.
3226 std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySaplingNotes(const CTransaction &tx) const
3228 LOCK(cs_SpendingKeyStore);
3229 uint256 hash = tx.GetHash();
3231 mapSaplingNoteData_t noteData;
3232 SaplingIncomingViewingKeyMap viewingKeysToAdd;
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);
3243 auto address = ivk.address(result.get().d);
3244 if (address && mapSaplingIncomingViewingKeys.count(address.get()) == 0) {
3245 viewingKeysToAdd[address.get()] = ivk;
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};
3252 noteData.insert(std::make_pair(op, nd));
3257 return std::make_pair(noteData, viewingKeysToAdd);
3260 bool CWallet::IsSproutNullifierFromMe(const uint256& nullifier) const
3264 if (mapSproutNullifiersToNotes.count(nullifier) &&
3265 mapWallet.count(mapSproutNullifiersToNotes.at(nullifier).hash)) {
3272 bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const
3276 if (mapSaplingNullifiersToNotes.count(nullifier) &&
3277 mapWallet.count(mapSaplingNullifiersToNotes.at(nullifier).hash)) {
3284 void CWallet::GetSproutNoteWitnesses(std::vector<JSOutPoint> notes,
3285 std::vector<boost::optional<SproutWitness>>& witnesses,
3286 uint256 &final_anchor)
3289 witnesses.resize(notes.size());
3290 boost::optional<uint256> rt;
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();
3298 rt = witnesses[i]->root();
3300 assert(*rt == witnesses[i]->root());
3305 // All returned witnesses have the same anchor
3311 void CWallet::GetSaplingNoteWitnesses(std::vector<SaplingOutPoint> notes,
3312 std::vector<boost::optional<SaplingWitness>>& witnesses,
3313 uint256 &final_anchor)
3316 witnesses.resize(notes.size());
3317 boost::optional<uint256> rt;
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();
3325 rt = witnesses[i]->root();
3327 assert(*rt == witnesses[i]->root());
3332 // All returned witnesses have the same anchor
3338 isminetype CWallet::IsMine(const CTxIn &txin, uint32_t nHeight) const
3342 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3343 if (mi != mapWallet.end())
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));
3353 CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter, uint32_t nHeight) const
3357 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3358 if (mi != mapWallet.end())
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?
3369 CCurrencyValueMap CWallet::GetReserveDebit(const CTxIn &txin, const isminefilter& filter, uint32_t nHeight) const
3373 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3374 if (mi != mapWallet.end())
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();
3382 return CCurrencyValueMap();
3385 isminetype CWallet::IsMine(const CTxOut& txout, uint32_t nHeight) const
3387 return ::IsMine(*this, txout.scriptPubKey, nHeight);
3390 CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter, uint32_t nHeight) const
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);
3397 bool CWallet::IsChange(const CTxOut& txout) const
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))
3408 CTxDestination address;
3409 if (!ExtractDestination(txout.scriptPubKey, address))
3413 if (!mapAddressBook.count(address))
3419 CAmount CWallet::GetChange(const CTxOut& txout) const
3421 if (!MoneyRange(txout.nValue))
3422 throw std::runtime_error("CWallet::GetChange(): value out of range");
3423 return (IsChange(txout) ? txout.nValue : 0);
3426 typedef vector<unsigned char> valtype;
3427 unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore);
3429 bool CWallet::IsMine(const CTransaction& tx, uint32_t nHeight)
3431 for (int i = 0; i < tx.vout.size(); i++)
3434 IsMine(tx, i, mine, nHeight);
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)
3445 vector<valtype> vSolutions;
3446 txnouttype whichType;
3447 CScript scriptPubKey = tx.vout[voutNum].scriptPubKey;
3449 if (scriptPubKey.IsCheckLockTimeVerify())
3451 uint8_t pushOp = scriptPubKey[0];
3452 uint32_t scriptStart = pushOp + 3;
3454 // continue with post CLTV script
3455 scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end());
3459 if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
3461 std::vector<CTxDestination> dests;
3463 bool canSign = false;
3464 bool canSpend = false;
3466 if (ExtractDestinations(scriptPubKey, whichType, dests, minSigs, this, &canSign, &canSpend, nHeight))
3470 mine = ISMINE_SPENDABLE;
3475 mine = ISMINE_WATCH_ONLY;
3490 else if (!Solver(scriptPubKey, whichType, vSolutions))
3492 if (this->HaveWatchOnly(scriptPubKey))
3494 mine = ISMINE_WATCH_ONLY;
3503 CScriptExt subscript;
3504 int voutNext = voutNum + 1;
3508 case TX_NONSTANDARD:
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)
3517 keyID = CPubKey(vSolutions[0]).GetID();
3519 else if (vSolutions[0].size() == 20)
3521 keyID = CKeyID(uint160(vSolutions[0]));
3523 if (!keyID.IsNull() && HaveKey(keyID))
3525 mine = ISMINE_SPENDABLE;
3531 keyID = CPubKey(vSolutions[0]).GetID();
3532 if (this->HaveKey(keyID))
3534 mine = ISMINE_SPENDABLE;
3540 keyID = CKeyID(uint160(vSolutions[0]));
3541 if (this->HaveKey(keyID))
3543 mine = ISMINE_SPENDABLE;
3549 scriptID = CScriptID(uint160(vSolutions[0]));
3550 if (this->GetCScript(scriptID, subscript))
3552 // if this is a CLTV, handle it differently
3553 if (subscript.IsCheckLockTimeVerify())
3555 mine = (::IsMine(*this, subscript));
3560 isminetype ret = ::IsMine(*this, subscript);
3561 if (ret == ISMINE_SPENDABLE)
3568 else if (tx.vout.size() > (voutNum + 1) &&
3569 tx.vout.back().scriptPubKey.size() > 7 &&
3570 tx.vout.back().scriptPubKey[0] == OP_RETURN)
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
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))
3579 if (opretData.size() > 0 && opretData[0] == OPRETTYPE_TIMELOCK)
3581 CScript opretScript = CScript(opretData.begin() + 1, opretData.end());
3583 if (CScriptID(opretScript) == scriptID &&
3584 opretScript.IsCheckLockTimeVerify())
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);
3591 this->AddCScript(opretScript);
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())
3610 mine = ISMINE_SPENDABLE;
3616 if (this->HaveWatchOnly(scriptPubKey))
3618 mine = ISMINE_WATCH_ONLY;
3625 bool CWallet::IsFromMe(const CTransaction& tx, uint32_t height) const
3629 for (auto &txin : tx.vin)
3631 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
3632 if (mi != mapWallet.end())
3634 const CWalletTx& prev = (*mi).second;
3635 if (txin.prevout.n < prev.vout.size())
3637 if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey, height) & ISMINE_ALL)
3643 for (const JSDescription& jsdesc : tx.vJoinSplit) {
3644 for (const uint256& nullifier : jsdesc.nullifiers) {
3645 if (IsSproutNullifierFromMe(nullifier)) {
3650 for (const SpendDescription &spend : tx.vShieldedSpend) {
3651 if (IsSaplingNullifierFromMe(spend.nullifier)) {
3658 CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3661 BOOST_FOREACH(const CTxIn& txin, tx.vin)
3663 nDebit += GetDebit(txin, filter, nHeight);
3664 if (!MoneyRange(nDebit))
3665 throw std::runtime_error("CWallet::GetDebit(): value out of range");
3670 CCurrencyValueMap CWallet::GetReserveDebit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3672 CCurrencyValueMap retVal;
3673 BOOST_FOREACH(const CTxIn& txin, tx.vin)
3675 retVal += GetReserveDebit(txin, filter, nHeight);
3680 CAmount CWallet::GetCredit(const CTransaction& tx, const int32_t &voutNum, const isminefilter& filter, uint32_t nHeight) const
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);
3687 CCurrencyValueMap CWallet::GetReserveCredit(const CTransaction& tx, int32_t voutNum, const isminefilter& filter) const
3689 return ((IsMine(tx.vout[voutNum]) & filter) ? tx.vout[voutNum].ReserveOutValue() : CCurrencyValueMap());
3692 CCurrencyValueMap CWallet::GetReserveCredit(const CTransaction& tx, const isminefilter& filter) const
3694 CCurrencyValueMap nCredit;
3695 for (int i = 0; i < tx.vout.size(); i++)
3697 nCredit += GetReserveCredit(tx, i, filter);
3702 CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter, uint32_t nHeight) const
3704 CAmount nCredit = 0;
3705 for (int i = 0; i < tx.vout.size(); i++)
3707 nCredit += GetCredit(tx, i, filter, nHeight);
3712 CAmount CWallet::GetChange(const CTransaction& tx) const
3714 CAmount nChange = 0;
3715 BOOST_FOREACH(const CTxOut& txout, tx.vout)
3717 nChange += GetChange(txout);
3718 if (!MoneyRange(nChange))
3719 throw std::runtime_error("CWallet::GetChange(): value out of range");
3724 bool CWallet::IsHDFullyEnabled() const
3726 // Only Sapling addresses are HD for now
3730 void CWallet::GenerateNewSeed()
3734 auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
3736 int64_t nCreationTime = GetTime();
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");
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);
3752 bool CWallet::SetHDSeed(const HDSeed& seed)
3754 if (!CCryptoKeyStore::SetHDSeed(seed)) {
3765 return CWalletDB(strWalletFile).WriteHDSeed(seed);
3771 bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
3773 if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
3783 if (pwalletdbEncryption)
3784 return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
3786 return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
3791 HDSeed CWallet::GetHDSeedForRPC() const {
3793 if (!pwalletMain->GetHDSeed(seed)) {
3794 throw JSONRPCError(RPC_WALLET_ERROR, "HD seed not found");
3799 void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
3802 if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
3803 throw std::runtime_error(std::string(__func__) + ": writing chain failed");
3808 bool CWallet::LoadHDSeed(const HDSeed& seed)
3810 return CBasicKeyStore::SetHDSeed(seed);
3813 bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
3815 return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
3818 void CWalletTx::SetSproutNoteData(mapSproutNoteData_t ¬eData)
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;
3827 // If FindMySproutNotes() was used to obtain noteData,
3828 // this should never happen
3829 throw std::logic_error("CWalletTx::SetSproutNoteData(): Invalid note");
3834 void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData)
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;
3841 throw std::logic_error("CWalletTx::SetSaplingNoteData(): Invalid note");
3846 std::pair<SproutNotePlaintext, SproutPaymentAddress> CWalletTx::DecryptSproutNote(
3847 JSOutPoint jsop) const
3849 LOCK(pwallet->cs_wallet);
3851 auto nd = this->mapSproutNoteData.at(jsop);
3852 SproutPaymentAddress pa = nd.address;
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)));
3863 auto hSig = this->vJoinSplit[jsop.js].h_sig(*pzcashParams, this->joinSplitPubKey);
3865 SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
3867 this->vJoinSplit[jsop.js].ciphertexts[jsop.n],
3868 this->vJoinSplit[jsop.js].ephemeralKey,
3870 (unsigned char) jsop.n);
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()));
3886 boost::optional<std::pair<
3887 SaplingNotePlaintext,
3888 SaplingPaymentAddress>> CWalletTx::DecryptSaplingNote(SaplingOutPoint op) const
3890 // Check whether we can decrypt this SaplingOutPoint
3891 if (this->mapSaplingNoteData.count(op) == 0) {
3895 auto output = this->vShieldedOutput[op.n];
3896 auto nd = this->mapSaplingNoteData.at(op);
3898 auto maybe_pt = SaplingNotePlaintext::decrypt(
3899 output.encCiphertext,
3901 output.ephemeralKey,
3903 assert(static_cast<bool>(maybe_pt));
3904 auto notePt = maybe_pt.get();
3906 auto maybe_pa = nd.ivk.address(notePt.d);
3907 assert(static_cast<bool>(maybe_pa));
3908 auto pa = maybe_pa.get();
3910 return std::make_pair(notePt, pa);
3913 boost::optional<std::pair<
3914 SaplingNotePlaintext,
3915 SaplingPaymentAddress>> CWalletTx::RecoverSaplingNote(
3916 SaplingOutPoint op, std::set<uint256>& ovks) const
3918 auto output = this->vShieldedOutput[op.n];
3920 for (auto ovk : ovks) {
3921 auto outPt = SaplingOutgoingPlaintext::decrypt(
3922 output.outCiphertext,
3926 output.ephemeralKey);
3931 auto maybe_pt = SaplingNotePlaintext::decrypt(
3932 output.encCiphertext,
3933 output.ephemeralKey,
3937 assert(static_cast<bool>(maybe_pt));
3938 auto notePt = maybe_pt.get();
3940 return std::make_pair(notePt, SaplingPaymentAddress(notePt.d, outPt->pk_d));
3943 // Couldn't recover with any of the provided OutgoingViewingKeys
3947 int64_t CWalletTx::GetTxTime() const
3949 int64_t n = nTimeSmart;
3950 return n ? n : nTimeReceived;
3953 int CWalletTx::GetRequestCount() const
3955 // Returns -1 if it wasn't being tracked
3958 LOCK(pwallet->cs_wallet);
3962 if (!hashBlock.IsNull())
3964 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
3965 if (mi != pwallet->mapRequestCount.end())
3966 nRequests = (*mi).second;
3971 // Did anyone request this transaction?
3972 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
3973 if (mi != pwallet->mapRequestCount.end())
3975 nRequests = (*mi).second;
3977 // How about the block it's in?
3978 if (nRequests == 0 && !hashBlock.IsNull())
3980 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
3981 if (mi != pwallet->mapRequestCount.end())
3982 nRequests = (*mi).second;
3984 nRequests = 1; // If it's in someone else's block it must have got out
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
3997 listReceived.clear();
3999 strSentAccount = strFromAccount;
4001 // Is this tx sent/signed by me?
4002 CAmount nDebit = GetDebit(filter);
4004 bool isFromMyTaddr = false;
4006 for (auto &txin : vin)
4008 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(txin.prevout.hash);
4009 if (mi != pwallet->mapWallet.end())
4011 const CWalletTx& prev = (*mi).second;
4012 if (txin.prevout.n < prev.vout.size())
4014 if (::IsMine(*pwallet, prev.vout[txin.prevout.n].scriptPubKey) & filter)
4016 isFromMyTaddr = true;
4023 //bool isFromMyTaddr = pwallet->IsFromMe(*this); // IsFromMe(filter); // debit>0 means we signed/sent this transaction
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;
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;
4040 for (const uint256& nullifier : js.nullifiers) {
4041 if (pwallet->IsSproutNullifierFromMe(nullifier)) {
4047 // Check output side
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()) {
4058 myVpubOld += js.vpub_old;
4059 myVpubNew += js.vpub_new;
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");
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);
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);
4090 for (unsigned int i = 0; i < vout.size(); ++i)
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)
4099 // Don't report 'change' txouts
4100 if (!(filter & ISMINE_CHANGE) && pwallet->IsChange(txout))
4103 else if (!(fIsMine & filter))
4106 // In either case, we need to get the destination address
4107 CTxDestination address;
4108 if (!ExtractDestination(txout.scriptPubKey, address))
4110 //LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",this->GetHash().ToString()); complains on the opreturns
4111 address = CNoDestination();
4114 COutputEntry output = {address, txout.nValue, (int)i};
4116 // If we are debited by the transaction, add the output as a "sent" entry
4118 listSent.push_back(output);
4120 // If we are receiving the output, add it as a "received" entry
4121 if (fIsMine & filter)
4122 listReceived.push_back(output);
4126 void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
4127 CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
4129 nReceived = nSent = nFee = 0;
4132 string strSentAccount;
4133 list<COutputEntry> listReceived;
4134 list<COutputEntry> listSent;
4135 GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
4137 if (strAccount == strSentAccount)
4139 BOOST_FOREACH(const COutputEntry& s, listSent)
4144 LOCK(pwallet->cs_wallet);
4145 BOOST_FOREACH(const COutputEntry& r, listReceived)
4147 if (pwallet->mapAddressBook.count(r.destination))
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;
4153 else if (strAccount.empty())
4155 nReceived += r.amount;
4162 bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
4164 return pwalletdb->WriteTx(GetHash(), *this);
4167 void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
4168 std::vector<boost::optional<SproutWitness>>& witnesses,
4169 uint256 &final_anchor)
4171 witnesses.resize(commitments.size());
4172 CBlockIndex* pindex = chainActive.Genesis();
4173 SproutMerkleTree tree;
4177 ReadBlockFromDisk(block, pindex, Params().GetConsensus(), 1);
4179 BOOST_FOREACH(const CTransaction& tx, block.vtx)
4181 BOOST_FOREACH(const JSDescription& jsdesc, tx.vJoinSplit)
4183 BOOST_FOREACH(const uint256 ¬e_commitment, jsdesc.commitments)
4185 tree.append(note_commitment);
4187 BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
4189 wit->append(note_commitment);
4194 BOOST_FOREACH(uint256& commitment, commitments) {
4195 if (note_commitment == commitment) {
4196 witnesses.at(i) = tree.witness();
4204 uint256 current_anchor = tree.root();
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));
4211 pindex = chainActive.Next(pindex);
4214 // TODO: #93; Select a root via some heuristic.
4215 final_anchor = tree.root();
4217 BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
4219 assert(final_anchor == wit->root());
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.
4229 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
4232 int64_t nNow = GetTime();
4233 const CChainParams& chainParams = Params();
4235 CBlockIndex* pindex = pindexStart;
4237 std::vector<uint256> myTxHashes;
4240 LOCK2(cs_main, cs_wallet);
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);
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);
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))));
4256 ReadBlockFromDisk(block, pindex, Params().GetConsensus());
4257 BOOST_FOREACH(CTransaction& tx, block.vtx)
4259 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
4260 myTxHashes.push_back(tx.GetHash());
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));
4275 // Increment note witness caches
4276 ChainTipAdded(pindex, &block, sproutTree, saplingTree);
4278 pindex = chainActive.Next(pindex);
4279 if (GetTime() >= nNow + 60) {
4281 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->GetHeight(), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
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());
4297 ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
4302 void CWallet::ReacceptWalletTransactions()
4304 // If transactions aren't being broadcasted, don't let them into local mempool either
4305 if (!fBroadcastTransactions)
4307 LOCK2(cs_main, cs_wallet);
4308 std::map<int64_t, CWalletTx*> mapSorted;
4310 // Sort pending wallet transactions based on their initial wallet insertion order
4311 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
4313 const uint256& wtxid = item.first;
4314 CWalletTx& wtx = item.second;
4315 assert(wtx.GetHash() == wtxid);
4317 int nDepth = wtx.GetDepthInMainChain();
4319 if (!wtx.IsCoinBase() && nDepth < 0) {
4320 mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
4324 std::vector<uint256> vwtxh;
4326 // Try to add wallet transactions to memory pool
4327 BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted)
4329 CWalletTx& wtx = *(item.second);
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))
4337 bool invalid = state.IsInvalid(nDoS);
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);
4342 if (!wtx.IsCoinBase() && invalid && nDoS > 0)
4344 LogPrintf("erasing transaction %s\n", wtx.GetHash().GetHex().c_str());
4345 vwtxh.push_back(wtx.GetHash());
4349 for (auto hash : vwtxh)
4351 EraseFromWallet(hash);
4355 bool CWalletTx::RelayWalletTransaction()
4359 fprintf(stderr,"unexpected null pwallet in RelayWalletTransaction\n");
4362 assert(pwallet->GetBroadcastTransactions());
4365 if (GetDepthInMainChain() == 0)
4367 // if tx is expired, dont relay
4368 LogPrintf("Relaying wtx %s\n", GetHash().ToString());
4369 RelayTransaction((CTransaction)*this);
4376 set<uint256> CWalletTx::GetConflicts() const
4378 set<uint256> result;
4379 if (pwallet != NULL)
4381 uint256 myHash = GetHash();
4382 result = pwallet->GetConflicts(myHash);
4383 result.erase(myHash);
4388 CAmount CWalletTx::GetDebit(const isminefilter& filter) const
4394 if(filter & ISMINE_SPENDABLE)
4397 debit += nDebitCached;
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;
4407 if(filter & ISMINE_WATCH_ONLY)
4409 if(fWatchDebitCached)
4410 debit += nWatchDebitCached;
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;
4423 CCurrencyValueMap CWalletTx::GetReserveDebit(const isminefilter& filter) const
4426 return CCurrencyValueMap();
4428 int depth = this->GetDepthInMainChain();
4429 uint32_t height = chainActive.Height() - --depth;
4431 return pwallet->GetReserveDebit(*this, filter, height);
4434 CAmount CWalletTx::GetCredit(const isminefilter& filter) const
4436 // Must wait until coinbase is safely deep enough in the chain before valuing it
4437 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4441 if (filter & ISMINE_SPENDABLE)
4443 // GetBalance can assume transactions in mapWallet won't change
4445 credit += nCreditCached;
4448 int depth = this->GetDepthInMainChain();
4449 uint32_t height = chainActive.Height() - --depth;
4451 nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE, height);
4452 fCreditCached = true;
4453 credit += nCreditCached;
4456 if (filter & ISMINE_WATCH_ONLY)
4458 if (fWatchCreditCached)
4459 credit += nWatchCreditCached;
4462 int depth = this->GetDepthInMainChain();
4463 uint32_t height = chainActive.Height() - --depth;
4465 nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY, height);
4466 fWatchCreditCached = true;
4467 credit += nWatchCreditCached;
4473 bool CWalletTx::HasMatureCoins() const
4475 // Must wait until coinbase is safely deep enough in the chain before valuing it
4476 if (!(IsCoinBase() && GetBlocksToMaturity() > 0))
4482 for (auto oneout : vout)
4484 if (oneout.scriptPubKey.IsInstantSpend())
4493 CCurrencyValueMap CWalletTx::GetReserveCredit(const isminefilter& filter) const
4495 // Must wait until coinbase is safely deep enough in the chain before valuing it
4496 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4497 return CCurrencyValueMap();
4499 return pwallet->GetReserveCredit(*this, filter);
4502 CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
4504 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4506 if (fUseCache && fImmatureCreditCached)
4507 return nImmatureCreditCached;
4508 nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
4509 fImmatureCreditCached = true;
4510 return nImmatureCreditCached;
4516 CCurrencyValueMap CWalletTx::GetImmatureReserveCredit(bool fUseCache) const
4518 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4520 pwallet->GetReserveCredit(*this, ISMINE_SPENDABLE);
4523 return CCurrencyValueMap();
4526 CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
4531 // Must wait until coinbase is safely deep enough in the chain before valuing it
4532 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4535 if (fUseCache && fAvailableCreditCached)
4536 return nAvailableCreditCached;
4538 CAmount nCredit = 0;
4539 uint256 hashTx = GetHash();
4540 for (unsigned int i = 0; i < vout.size(); i++)
4542 if (!pwallet->IsSpent(hashTx, i) && vout[i].scriptPubKey.IsSpendableOutputType())
4544 nCredit += pwallet->GetCredit(*this, i, ISMINE_SPENDABLE);
4548 nAvailableCreditCached = nCredit;
4549 fAvailableCreditCached = true;
4553 CCurrencyValueMap CWalletTx::GetAvailableReserveCredit(bool fUseCache) const
4555 CCurrencyValueMap retVal;
4559 // Must wait until coinbase is safely deep enough in the chain before valuing it
4560 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4563 uint256 hashTx = GetHash();
4564 for (unsigned int i = 0; i < vout.size(); i++)
4566 if (!pwallet->IsSpent(hashTx, i) && vout[i].scriptPubKey.IsSpendableOutputType())
4568 retVal += pwallet->GetReserveCredit(*this, i, ISMINE_SPENDABLE);
4574 CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
4576 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4578 if (fUseCache && fImmatureWatchCreditCached)
4579 return nImmatureWatchCreditCached;
4580 nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
4581 fImmatureWatchCreditCached = true;
4582 return nImmatureWatchCreditCached;
4588 CCurrencyValueMap CWalletTx::GetImmatureWatchOnlyReserveCredit(const bool& fUseCache) const
4590 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
4592 return pwallet->GetReserveCredit(*this, ISMINE_WATCH_ONLY);
4595 return CCurrencyValueMap();
4598 CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
4603 // Must wait until coinbase is safely deep enough in the chain before valuing it
4604 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4607 if (fUseCache && fAvailableWatchCreditCached)
4608 return nAvailableWatchCreditCached;
4610 CAmount nCredit = 0;
4611 for (unsigned int i = 0; i < vout.size(); i++)
4613 if (!pwallet->IsSpent(GetHash(), i))
4615 nCredit += pwallet->GetCredit(*this, i, ISMINE_WATCH_ONLY);
4616 if (!MoneyRange(nCredit))
4617 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
4621 nAvailableWatchCreditCached = nCredit;
4622 fAvailableWatchCreditCached = true;
4626 CCurrencyValueMap CWalletTx::GetAvailableWatchOnlyReserveCredit(const bool& fUseCache) const
4628 CCurrencyValueMap retVal;
4632 // Must wait until coinbase is safely deep enough in the chain before valuing it
4633 if (IsCoinBase() && GetBlocksToMaturity() > 0)
4636 for (unsigned int i = 0; i < vout.size(); i++)
4638 if (!pwallet->IsSpent(GetHash(), i))
4640 retVal += pwallet->GetReserveCredit(*this, i, ISMINE_WATCH_ONLY);
4647 CAmount CWalletTx::GetChange() const
4650 return nChangeCached;
4651 nChangeCached = pwallet->GetChange(*this);
4652 fChangeCached = true;
4653 return nChangeCached;
4656 bool CWalletTx::IsTrusted() const
4658 // Quick answer in most cases
4659 if (!CheckFinalTx(*this))
4661 int nDepth = GetDepthInMainChain();
4666 if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
4669 // Trusted if all inputs are from us and are in the mempool:
4670 BOOST_FOREACH(const CTxIn& txin, vin)
4672 // Transactions not sent by us: not trusted
4673 const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
4676 if (!parent->vout.size())
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);
4681 const CTxOut& parentOut = parent->vout[txin.prevout.n];
4682 if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
4688 std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
4690 std::vector<uint256> result;
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)
4699 CWalletTx& wtx = item.second;
4700 // Don't rebroadcast if newer than nTime:
4701 if (wtx.nTimeReceived > nTime)
4703 if ( (wtx.nLockTime >= LOCKTIME_THRESHOLD && wtx.nLockTime < now-KOMODO_MAXMEMPOOLTIME) || wtx.hashBlock.IsNull() )
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());
4709 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
4711 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
4713 if ( item.second != 0 )
4715 CWalletTx &wtx = *item.second;
4716 if (wtx.RelayWalletTransaction())
4717 result.push_back(wtx.GetHash());
4720 for (auto hash : vwtxh)
4722 EraseFromWallets(hash);
4727 void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
4729 // Do this infrequently and randomly to avoid giving away
4730 // that these are our transactions.
4731 if (GetTime() < nNextResend || !fBroadcastTransactions)
4733 bool fFirst = (nNextResend == 0);
4734 nNextResend = GetTime() + GetRand(30 * 60);
4738 // Only do it if there's been a new block since last time
4739 if (nBestBlockTime < nLastResend)
4741 nLastResend = GetTime();
4743 // Rebroadcast unconfirmed txes older than 5 minutes before the last
4745 std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60);
4746 if (!relayed.empty())
4747 LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
4750 /** @} */ // end of mapWallet
4755 /** @defgroup Actions
4761 CAmount CWallet::GetBalance() const
4765 LOCK2(cs_main, cs_wallet);
4766 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4768 const CWalletTx* pcoin = &(*it).second;
4769 if (pcoin->IsTrusted())
4770 nTotal += pcoin->GetAvailableCredit();
4777 CCurrencyValueMap CWallet::GetReserveBalance() const
4779 CCurrencyValueMap retVal;
4781 LOCK2(cs_main, cs_wallet);
4782 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4784 const CWalletTx* pcoin = &(*it).second;
4785 if (pcoin->IsTrusted())
4786 retVal += pcoin->GetAvailableReserveCredit();
4793 CAmount CWallet::GetUnconfirmedBalance() const
4797 LOCK2(cs_main, cs_wallet);
4798 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4800 const CWalletTx* pcoin = &(*it).second;
4801 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4802 nTotal += pcoin->GetAvailableCredit();
4808 CCurrencyValueMap CWallet::GetUnconfirmedReserveBalance() const
4810 CCurrencyValueMap retVal;
4812 LOCK2(cs_main, cs_wallet);
4813 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4815 const CWalletTx* pcoin = &(*it).second;
4816 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4817 retVal += pcoin->GetAvailableReserveCredit();
4823 CAmount CWallet::GetImmatureBalance() const
4827 LOCK2(cs_main, cs_wallet);
4828 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4830 const CWalletTx* pcoin = &(*it).second;
4831 nTotal += pcoin->GetImmatureCredit();
4837 CCurrencyValueMap CWallet::GetImmatureReserveBalance() const
4839 CCurrencyValueMap retVal;
4841 LOCK2(cs_main, cs_wallet);
4842 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4844 const CWalletTx* pcoin = &(*it).second;
4845 retVal += pcoin->GetImmatureReserveCredit();
4851 CAmount CWallet::GetWatchOnlyBalance() const
4855 LOCK2(cs_main, cs_wallet);
4856 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4858 const CWalletTx* pcoin = &(*it).second;
4859 if (pcoin->IsTrusted())
4860 nTotal += pcoin->GetAvailableWatchOnlyCredit();
4867 CCurrencyValueMap CWallet::GetWatchOnlyReserveBalance() const
4869 CCurrencyValueMap retVal;
4871 LOCK2(cs_main, cs_wallet);
4872 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4874 const CWalletTx* pcoin = &(*it).second;
4875 if (pcoin->IsTrusted())
4876 retVal += pcoin->GetAvailableWatchOnlyReserveCredit();
4883 CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
4887 LOCK2(cs_main, cs_wallet);
4888 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4890 const CWalletTx* pcoin = &(*it).second;
4891 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4892 nTotal += pcoin->GetAvailableWatchOnlyCredit();
4898 CCurrencyValueMap CWallet::GetUnconfirmedWatchOnlyReserveBalance() const
4900 CCurrencyValueMap retVal;
4902 LOCK2(cs_main, cs_wallet);
4903 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4905 const CWalletTx* pcoin = &(*it).second;
4906 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
4907 retVal += pcoin->GetAvailableWatchOnlyReserveCredit();
4913 CAmount CWallet::GetImmatureWatchOnlyBalance() const
4917 LOCK2(cs_main, cs_wallet);
4918 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4920 const CWalletTx* pcoin = &(*it).second;
4921 nTotal += pcoin->GetImmatureWatchOnlyCredit();
4927 CCurrencyValueMap CWallet::GetImmatureWatchOnlyReserveBalance() const
4929 CCurrencyValueMap retVal;
4931 LOCK2(cs_main, cs_wallet);
4932 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
4934 const CWalletTx* pcoin = &(*it).second;
4935 retVal += pcoin->GetImmatureWatchOnlyReserveCredit();
4942 * populate vCoins with vector of available COutputs.
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);
4947 void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase, bool fIncludeProtectedCoinbase, bool fIncludeImmatureCoins) const
4949 uint64_t interest,*ptr;
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)
4957 const uint256& wtxid = it->first;
4958 const CWalletTx* pcoin = &(*it).second;
4960 if (!CheckFinalTx(*pcoin))
4963 if (fOnlyConfirmed && !pcoin->IsTrusted())
4966 bool isCoinbase = pcoin->IsCoinBase();
4967 if (!fIncludeCoinBase && isCoinbase)
4970 if (!fIncludeImmatureCoins && isCoinbase && pcoin->GetBlocksToMaturity() > 0)
4973 int nDepth = pcoin->GetDepthInMainChain();
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
4980 !fIncludeProtectedCoinbase &&
4981 Params().GetConsensus().fCoinbaseMustBeProtected &&
4982 CConstVerusSolutionVector::GetVersionByHeight(coinHeight) < CActivationHeight::SOLUTION_VERUSV4 &&
4983 CConstVerusSolutionVector::GetVersionByHeight(nHeight) < CActivationHeight::SOLUTION_VERUSV5)
4986 for (int i = 0; i < pcoin->vout.size(); i++)
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)))
4993 if ( KOMODO_EXCHANGEWALLET == 0 )
4995 uint32_t locktime; int32_t txheight; CBlockIndex *tipindex;
4996 if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->GetHeight() >= 60000 )
4998 if ( pcoin->vout[i].nValue >= 10*COIN )
5000 if ( (tipindex= chainActive.LastTip()) != 0 )
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 )
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;
5014 //pcoin->vout[i].nValue += interest;
5018 ptr = (uint64_t *)&pcoin->vout[i].interest;
5024 ptr = (uint64_t *)&pcoin->vout[i].interest;
5030 ptr = (uint64_t *)&pcoin->vout[i].interest;
5034 vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
5041 void CWallet::AvailableReserveCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeCoinBase, bool fIncludeNative, const CTxDestination *pOnlyFromDest, const CCurrencyValueMap *pOnlyTheseCurrencies) const
5046 LOCK2(cs_main, cs_wallet);
5047 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
5049 const uint256& wtxid = it->first;
5050 const CWalletTx* pcoin = &(*it).second;
5052 if (!CheckFinalTx(*pcoin))
5055 if (fOnlyConfirmed && !pcoin->IsTrusted())
5058 if (pcoin->IsCoinBase() && !fIncludeCoinBase)
5061 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
5064 int nDepth = pcoin->GetDepthInMainChain();
5068 for (int i = 0; i < pcoin->vout.size(); i++)
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)))
5077 CCurrencyValueMap rOut = pcoin->vout[i].scriptPubKey.ReserveOutValue(p, true);
5079 if (p.IsValid() && !pcoin->vout[i].scriptPubKey.IsSpendableOutputType(p))
5088 for (auto &oneDest : p.vKeys)
5090 if (GetDestinationID(oneDest) == GetDestinationID(*pOnlyFromDest))
5103 // support P2PK or P2PKH
5104 CTxDestination dest;
5105 if (!ExtractDestination(pcoin->vout[i].scriptPubKey, dest) || GetDestinationID(dest) != GetDestinationID(*pOnlyFromDest))
5111 // don't return zero valued outputs
5112 if (rOut.CanonicalMap().valueMap.size() || pcoin->vout[i].nValue)
5114 if ((rOut.valueMap.size() && (!pOnlyTheseCurrencies || (pOnlyTheseCurrencies && pOnlyTheseCurrencies->Intersects(rOut)))) ||
5115 (fIncludeNative && pcoin->vout[i].nValue))
5117 vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
5126 bool CWallet::GetAndValidateSaplingZAddress(const std::string &addressStr, libzcash::PaymentAddress &zaddress)
5128 std::string addrCopy = addressStr;
5129 std::vector<std::string> addressParts;
5130 boost::split(addressParts, addrCopy, boost::is_any_of(":"));
5132 if (addressParts.size() == 2 && addressParts[1] == "private")
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)
5138 AssertLockHeld(cs_main);
5139 CIdentity idSource = CIdentity::LookupIdentity(GetDestinationID(destination));
5140 if (idSource.IsValid() && idSource.privateAddresses.size() > 0)
5142 zaddress = idSource.privateAddresses[0];
5146 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid ID or ID that does not have valid z-address specified");
5149 zaddress = DecodePaymentAddress(addrCopy);
5150 bool hasZSource = boost::get<libzcash::SaplingPaymentAddress>(&zaddress) != nullptr;
5151 if (!hasZSource && boost::get<libzcash::SproutPaymentAddress>(&zaddress) != nullptr)
5153 throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy Sprout address not supported. Use a transparent or Sapling compatible address");
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)
5160 vector<char> vfIncluded;
5162 vfBest.assign(vValue.size(), true);
5163 nBest = nTotalLower;
5165 seed_insecure_rand();
5167 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
5169 vfIncluded.assign(vValue.size(), false);
5171 bool fReachedTarget = false;
5172 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
5174 for (unsigned int i = 0; i < vValue.size(); i++)
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])
5184 nTotal += vValue[i].first;
5185 vfIncluded[i] = true;
5186 if (nTotal >= nTargetValue)
5188 fReachedTarget = true;
5192 vfBest = vfIncluded;
5194 nTotal -= vValue[i].first;
5195 vfIncluded[i] = false;
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
5207 bool CloserToTarget(const CCurrencyValueMap &target, const CCurrencyValueMap ¤t, const CCurrencyValueMap &candidate)
5209 CCurrencyValueMap workingTarget = target.SubtractToZero(current); // whatever is left is what we still need
5210 return workingTarget.SubtractToZero(candidate) < workingTarget;
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)
5220 vector<char> vfIncluded;
5222 vfBest.assign(vValue.size(), true);
5223 bestTotals = totalToOptimize;
5225 seed_insecure_rand();
5227 for (int nRep = 0; nRep < iterations && bestTotals != targetValues; nRep++)
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++)
5235 CCurrencyValueMap adjustedTarget(targetValues);
5236 CCurrencyValueMap presentValues;
5237 for (unsigned int i = 0; i < vValue.size(); i++)
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.
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));
5252 if ((nPass == 0 ? insecure_rand()&1 : !vfIncluded[i]) && CloserToTarget(targetValues, totals, vValue[i].first))
5254 totals += vValue[i].first.IntersectingValues(targetValues);
5255 vfIncluded[i] = true;
5256 // we reached the target if we fulfill all currencies
5258 adjustedTarget = targetValues.SubtractToZero(totals);
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)
5263 satisfied.insert(oneCur.first);
5266 if (satisfied.size() == targetValues.valueMap.size())
5268 fReachedTarget = true;
5269 CompareValueMap comparator(targetValues);
5270 if (comparator.CompareMaps(totals, bestTotals))
5272 bestTotals = totals;
5273 vfBest = vfIncluded;
5275 totals -= vValue[i].first;
5276 vfIncluded[i] = false;
5284 bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
5286 int32_t count = 0; //uint64_t lowest_interest = 0;
5287 setCoinsRet.clear();
5288 //memset(interests,0,sizeof(interests));
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;
5297 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
5299 BOOST_FOREACH(const COutput &output, vCoins)
5301 if (!output.fSpendable)
5304 if (output.tx->vout[output.i].nValue == 0)
5309 const CWalletTx *pcoin = output.tx;
5311 if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
5315 CAmount n = pcoin->vout[i].nValue;
5317 pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
5319 if (n == nTargetValue)
5321 setCoinsRet.insert(coin.second);
5322 nValueRet += coin.first;
5323 //if ( KOMODO_EXCHANGEWALLET == 0 )
5324 // *interestp += pcoin->vout[i].interest;
5327 else if (n < nTargetValue + CENT)
5329 vValue.push_back(coin);
5331 //if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) )
5333 //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN);
5334 //interests[count++] = pcoin->vout[i].interest;
5336 if ( nTotalLower > 4*nTargetValue + CENT )
5338 //fprintf(stderr,"why bother with all the utxo if we have double what is needed?\n");
5342 else if (n < coinLowestLarger.first)
5344 coinLowestLarger = coin;
5345 //if ( KOMODO_EXCHANGEWALLET == 0 )
5346 // lowest_interest = pcoin->vout[i].interest;
5350 if (nTotalLower == nTargetValue)
5352 for (unsigned int i = 0; i < vValue.size(); ++i)
5354 setCoinsRet.insert(vValue[i].second);
5355 nValueRet += vValue[i].first;
5356 //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
5357 // *interestp += interests[i];
5362 if (nTotalLower < nTargetValue)
5364 if (coinLowestLarger.second.first == NULL)
5366 setCoinsRet.insert(coinLowestLarger.second);
5367 nValueRet += coinLowestLarger.first;
5368 //if ( KOMODO_EXCHANGEWALLET == 0 )
5369 // *interestp += lowest_interest;
5373 // Solve subset sum by stochastic approximation
5374 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
5375 vector<char> vfBest;
5378 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
5379 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
5380 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
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))
5387 setCoinsRet.insert(coinLowestLarger.second);
5388 nValueRet += coinLowestLarger.first;
5389 //if ( KOMODO_EXCHANGEWALLET == 0 )
5390 // *interestp += lowest_interest;
5393 for (unsigned int i = 0; i < vValue.size(); i++)
5396 setCoinsRet.insert(vValue[i].second);
5397 nValueRet += vValue[i].first;
5398 //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
5399 // *interestp += interests[i];
5402 LogPrint("selectcoins", "SelectCoins() best subset: ");
5403 for (unsigned int i = 0; i < vValue.size(); i++)
5405 LogPrint("selectcoins", "%s", FormatMoney(vValue[i].first));
5406 LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
5412 bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyProtectedCoinbaseCoinsRet, bool& fNeedProtectedCoinbaseCoinsRet, const CCoinControl* coinControl) const
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 )
5418 // interestp = &tmp;
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;
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;
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()) {
5433 for (const COutput& out : vCoinsNoCoinbase) {
5434 if (!out.fSpendable) {
5437 value += out.tx->vout[out.i].nValue;
5438 if ( KOMODO_EXCHANGEWALLET == 0 )
5439 value += out.tx->vout[out.i].interest;
5441 if (value <= nTargetValue) {
5442 CAmount valueWithCoinbase = 0;
5443 for (const COutput& out : vCoinsWithCoinbase) {
5444 if (!out.fSpendable) {
5447 valueWithCoinbase += out.tx->vout[out.i].nValue;
5448 if ( KOMODO_EXCHANGEWALLET == 0 )
5449 valueWithCoinbase += out.tx->vout[out.i].interest;
5451 fNeedProtectedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
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)
5457 BOOST_FOREACH(const COutput& out, vCoins)
5459 if (!out.fSpendable)
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));
5466 return (nValueRet >= nTargetValue);
5468 // calculate value from preset inputs and store them
5469 set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
5470 CAmount nValueFromPresetInputs = 0;
5472 std::vector<COutPoint> vPresetInputs;
5474 coinControl->ListSelected(vPresetInputs);
5475 BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
5477 map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
5478 if (it != mapWallet.end())
5480 const CWalletTx* pcoin = &it->second;
5481 // Clearly invalid input, fail
5482 if (pcoin->vout.size() <= outpoint.n)
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));
5489 return false; // TODO: Allow non-wallet inputs
5492 // remove preset inputs from vCoins
5493 for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
5495 if (setPresetCoins.count(make_pair(it->tx, it->i)))
5496 it = vCoins.erase(it);
5501 if ( nTargetValue <= nValueFromPresetInputs )
5503 else if ( SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) != 0 )
5505 else if ( SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) != 0 )
5507 else if ( bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet) != 0 )
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;
5516 bool CWallet::SelectReserveCoinsMinConf(const CCurrencyValueMap& targetValues,
5517 CAmount targetNativeValue,
5520 std::vector<COutput> vCoins,
5521 std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet,
5522 CCurrencyValueMap& valueRet,
5523 CAmount &nativeValueRet) const
5525 int32_t count = 0; //uint64_t lowest_interest = 0;
5526 setCoinsRet.clear();
5527 valueRet.valueMap.clear();
5529 //memset(interests,0,sizeof(interests));
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;
5541 CCurrencyValueMap nativeCent(std::vector<uint160>({ASSETCHAINS_CHAINID}), std::vector<CAmount>({CENT}));
5543 CCurrencyValueMap totalToOptimize;
5544 std::vector<std::pair<CCurrencyValueMap, std::pair<const CWalletTx*, unsigned int>>> vOutputsToOptimize;
5546 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
5548 CCurrencyValueMap nTotalTarget = (targetValues + CCurrencyValueMap(std::vector<uint160>({ASSETCHAINS_CHAINID}), std::vector<CAmount>({targetNativeValue}))).CanonicalMap();
5550 //printf("totaltarget: %s\n", nTotalTarget.ToUniValue().write().c_str());
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);
5556 for (const COutput &output : vCoins)
5558 if (!output.fSpendable)
5561 const CWalletTx *pcoin = output.tx;
5563 if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
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;
5572 nAll.valueMap[ASSETCHAINS_CHAINID] = nativeN;
5573 if (targetNativeValue)
5575 nTotal.valueMap[ASSETCHAINS_CHAINID] = nativeN;
5579 // if it has no output types we care about, next
5580 if (!nTotal.valueMap.size())
5585 //printf("nTotal: %s\n", nTotal.ToUniValue().write().c_str());
5587 CReserveOutSelectionInfo coin(pcoin, i, nAll);
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)
5593 setCoinsRet.insert(std::make_pair(coin.pWtx, coin.n));
5594 valueRet = pcoin->vout[i].scriptPubKey.ReserveOutValue();
5595 nativeValueRet = nativeN;
5599 CCurrencyValueMap subtractedFromTarget(nTotalTarget.SubtractToZero(nTotal));
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
5604 std::vector<uint160> multiCurrencies;
5606 COutput sanitizedOutput(output.tx, output.i, 0, true);
5608 // if we have some entries larger than target
5609 if (subtractedFromTarget.valueMap.size() < nTotalTarget.valueMap.size())
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)
5614 coinsLowestLarger[oneCur.first].insert(std::make_pair(oneCur.second, CReserveOutSelectionInfo(output.tx, output.i, nAll)));
5615 multiCurrencies.push_back(oneCur.first);
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)));
5627 bool neededCurrency = false;
5628 for (auto &oneCur : nTotal.valueMap)
5630 if (satisfied_x4.count(oneCur.first))
5634 neededCurrency = true;
5635 coinsLargestLower[oneCur.first].insert(std::make_pair(oneCur.second, coin));
5637 if (!neededCurrency)
5642 lowerOuts.insert(std::make_pair(std::make_pair(output.tx, output.i), nAll));
5643 lowerTotal += nTotal;
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());
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)
5651 //printf("satisfied x 4: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5652 satisfied_x4.insert(oneCur.first);
5655 if (satisfied_x4.size() == nTotalTarget.valueMap.size())
5657 //printf("short circuit lower: lowerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5663 std::set<uint160> satisfied_larger;
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
5669 // if our lower total + larger total are not enough, no way we have enough
5670 if ((lowerTotal + largerTotal) < nTotalTarget)
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());
5677 for (auto &lowerOut : lowerOuts)
5679 totalToOptimize += lowerOut.second;
5680 vOutputsToOptimize.push_back(std::make_pair(lowerOut.second, std::make_pair(lowerOut.first.first, lowerOut.first.second)));
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);
5686 if ((lowerTotal >= nTotalTarget && lowerTotal <= (nTotalTarget + nativeCent)) && lowerOuts.size() <= numInputsLimit)
5688 //printf("selecting all lowers\nlowerTotal:\n%s\nTotalTarget:\n%s\n", lowerTotal.ToUniValue().write().c_str(), nTotalTarget.ToUniValue().write().c_str());
5690 for (auto oneOut : lowerOuts)
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;
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());
5701 std::map<std::pair<const CWalletTx *, int>, CReserveOutSelectionInfo> added;
5702 largerTotal.valueMap.clear();
5703 CCurrencyValueMap adjustedTarget;
5704 std::set<uint160> satisfied;
5706 // short circuit best fit check with any exact amounts we may have
5707 if (multiSatisfy.size())
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
5712 // check in reverse to check those that satisfy most first
5713 for (auto multiIt = multiSatisfy.rbegin(); multiIt != multiSatisfy.rend(); multiIt++)
5715 // if we have 0 left, we're done
5716 if (nTotalTarget.valueMap.size() == satisfied.size())
5718 //printf("satisfied all currencies. lowerTotal:\n%s\n", largerTotal.ToUniValue().write().c_str());
5722 // consider "satisfying" an exact match of any currency in the adjusted request, otherwise, we should fall through to the best fit solver
5724 for (auto &oneCurID : multiIt->second.first)
5726 if (!satisfied.count(oneCurID) &&
5727 multiIt->second.second.outVal.valueMap[oneCurID] == adjustedTarget.valueMap[oneCurID])
5733 std::pair<const CWalletTx *, unsigned int> outPair({multiIt->second.second.pWtx, multiIt->second.second.n});
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))
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));
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);
5751 // printf("adjustedTarget:\n%s\ntotalAdded:\n%s\n", adjustedTarget.ToUniValue().write().c_str(), totalAdded.ToUniValue().write().c_str());
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());
5756 adjustedTarget = nTotalTarget.SubtractToZero(largerTotal);
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)
5761 //printf("satisfied: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5762 satisfied.insert(oneCur.first);
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())
5770 for (auto &oneOut : added)
5772 setCoinsRet.insert(std::make_pair(oneOut.second.pWtx, oneOut.second.n));
5773 valueRet += oneOut.second.outVal;
5775 auto vRetIt = valueRet.valueMap.find(ASSETCHAINS_CHAINID);
5776 if (vRetIt != valueRet.valueMap.end())
5778 nativeValueRet = vRetIt->second;
5779 valueRet.valueMap.erase(vRetIt);
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)
5788 satisfied_x4.insert(oneCurID);
5790 for (auto &largerOut : largerOuts)
5792 COutput thisOutput(largerOut.first.first, largerOut.first.second, 0, true);
5793 if (lowerOuts.count(std::make_pair(largerOut.first.first, largerOut.first.second)))
5797 // if we have more, they only go into the lower, if they have
5798 // coins in the currencies where we are not satisfied
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());
5802 bool useThis = false;
5803 for (auto &oneCur : largerOut.second.IntersectingValues(nTotalTarget).valueMap)
5805 if (!satisfied.count(oneCur.first) && !satisfied_x4.count(oneCur.first))
5813 CReserveOutSelectionInfo coin(largerOut.first.first, largerOut.first.second, largerOut.second);
5815 for (auto &oneCur : largerOut.second.valueMap)
5817 coinsLargestLower[oneCur.first].insert(std::make_pair(oneCur.second, coin));
5820 lowerOuts.insert(std::make_pair(std::make_pair(largerOut.first.first, largerOut.first.second), largerOut.second));
5822 lowerTotal += largerOut.second;
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());
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)
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)
5833 //printf("satisfied x 4: %s\n", EncodeDestination(CIdentityID(oneCur.first)).c_str());
5834 satisfied_x4.insert(oneCur.first);
5837 totalToOptimize += largerOut.second;
5838 vOutputsToOptimize.push_back(std::make_pair(largerOut.second, std::make_pair(largerOut.first.first, largerOut.first.second)));
5842 //printf("\nlargerTotal:\n%s\n", largerTotal.ToUniValue().write().c_str());
5843 // printf("adjustedTarget:\n%s\n", adjustedTarget.ToUniValue().write().c_str());
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;
5850 for (int i = 0; i < vOutputsToOptimize.size(); i++)
5852 if (added.count(vOutputsToOptimize[i].second))
5854 vOutputsToRemove.push_back(i);
5855 removedValue += vOutputsToOptimize[i].first;
5859 for (auto &oneOutput : added)
5861 setCoinsRet.insert(std::make_pair(oneOutput.second.pWtx, oneOutput.second.n));
5862 valueRet += oneOutput.second.outVal;
5864 auto vRetIt = valueRet.valueMap.find(ASSETCHAINS_CHAINID);
5865 if (vRetIt != valueRet.valueMap.end())
5867 nativeValueRet = vRetIt->second;
5868 valueRet.valueMap.erase(vRetIt);
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--)
5875 vOutputsToOptimize.erase(vOutputsToOptimize.begin() + vOutputsToRemove[i]);
5878 totalToOptimize = totalToOptimize.SubtractToZero(removedValue);
5879 CCurrencyValueMap newOptimizationTarget = nTotalTarget.SubtractToZero(largerTotal);
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++)
5884 printf("output #%d:\nreserves:\n%s\nnative:\n%s\n",
5886 vOutputsToOptimize[i].first.ToUniValue().write().c_str(),
5887 ValueFromAmount(vOutputsToOptimize[i].second.first->vout[vOutputsToOptimize[i].second.second].nValue).write().c_str());
5890 vector<char> vfBest;
5891 CCurrencyValueMap bestTotals;
5893 ApproximateBestReserveSubset(vOutputsToOptimize, totalToOptimize, newOptimizationTarget, vfBest, bestTotals, 1000);
5894 if (bestTotals != newOptimizationTarget && totalToOptimize >= newOptimizationTarget + nativeCent)
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);
5900 for (unsigned int i = 0; i < vOutputsToOptimize.size(); i++)
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()); */
5914 CCurrencyValueMap checkReturn(valueRet);
5915 checkReturn.valueMap[ASSETCHAINS_CHAINID] = nativeValueRet;
5917 if (checkReturn.IntersectingValues(nTotalTarget) < nTotalTarget)
5922 LogPrint("selectcoins", "SelectCoins() best subset: ");
5923 for (unsigned int i = 0; i < vOutputsToOptimize.size(); i++)
5927 LogPrint("selectcoins", "%s", FormatMoney(vOutputsToOptimize[i].first.valueMap[targetValues.valueMap.begin()->first]));
5930 LogPrint("selectcoins", "total %s\n", FormatMoney(bestTotals.valueMap[targetValues.valueMap.begin()->first]));
5935 bool CWallet::SelectReserveCoins(const CCurrencyValueMap& targetReserveValues,
5936 CAmount targetNativeValue,
5937 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet,
5938 CCurrencyValueMap &valueRet,
5940 bool& fOnlyCoinbaseCoinsRet,
5941 bool& fNeedCoinbaseCoinsRet,
5942 const CCoinControl* coinControl,
5943 const CTxDestination *pOnlyFromDest) const
5945 // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
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;
5952 // coinbase protection forcing them to be spent only to z-addresses ended
5953 // when identities were released
5954 bool fProtectCoinbase = false;
5956 vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
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) {
5966 nativeValue += out.tx->vout[out.i].nValue;
5967 reserveValues += out.tx->vout[out.i].ReserveOutValue();
5969 if (reserveValues < targetReserveValues || nativeValue < targetNativeValue) {
5970 CCurrencyValueMap reserveValuesWithCoinbase;
5971 CAmount nativeValueWithCoinbase = 0;
5972 for (const COutput& out : vCoinsWithCoinbase) {
5973 if (!out.fSpendable) {
5976 reserveValuesWithCoinbase += out.tx->vout[out.i].ReserveOutValue();
5977 nativeValueWithCoinbase += out.tx->vout[out.i].nValue;
5979 fNeedCoinbaseCoinsRet = (reserveValuesWithCoinbase >= targetReserveValues) && (nativeValueWithCoinbase >= targetNativeValue);
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)
5986 BOOST_FOREACH(const COutput& out, vCoins)
5988 if (!out.fSpendable)
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));
5994 return (valueRet >= targetReserveValues) && (nativeRet >= targetNativeValue);
5997 // calculate value from preset inputs and store them
5998 set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
5999 CCurrencyValueMap valueFromPresetInputs;
6000 CAmount nativeValueFromPresets = 0;
6002 std::vector<COutPoint> vPresetInputs;
6004 coinControl->ListSelected(vPresetInputs);
6005 BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
6007 map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
6008 if (it != mapWallet.end())
6010 const CWalletTx* pcoin = &it->second;
6011 // Clearly invalid input, fail
6012 if (pcoin->vout.size() <= outpoint.n)
6014 valueFromPresetInputs += pcoin->vout[outpoint.n].ReserveOutValue();
6015 nativeValueFromPresets += pcoin->vout[outpoint.n].nValue;
6016 setPresetCoins.insert(make_pair(pcoin, outpoint.n));
6018 return false; // TODO: Allow non-wallet inputs
6021 // remove preset inputs from vCoins
6022 for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
6024 if (setPresetCoins.count(make_pair(it->tx, it->i)))
6025 it = vCoins.erase(it);
6030 bool retval = false;
6031 if ( targetNativeValue <= nativeRet &&
6032 targetReserveValues <= targetReserveValues.IntersectingValues(valueFromPresetInputs) && targetNativeValue <= nativeValueFromPresets )
6034 else if ( SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 1, 6, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
6036 else if ( SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 1, 1, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
6038 else if ( bSpendZeroConfChange && SelectReserveCoinsMinConf(targetReserveValues, targetNativeValue, 0, 1, vCoins, setCoinsRet, valueRet, nativeRet) != 0 )
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;
6048 bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason)
6050 vector<CRecipient> vecSend;
6052 // Turn the txout set into a CRecipient vector
6053 BOOST_FOREACH(const CTxOut& txOut, tx.vout)
6055 CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false};
6056 vecSend.push_back(recipient);
6059 CCoinControl coinControl;
6060 coinControl.fAllowOtherInputs = true;
6061 BOOST_FOREACH(const CTxIn& txin, tx.vin)
6062 coinControl.Select(txin.prevout);
6064 CReserveKey reservekey(this);
6067 if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
6070 if (nChangePosRet != -1)
6071 tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
6073 // Add new txins (keeping original txin scriptSig/order)
6074 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
6077 BOOST_FOREACH(const CTxIn& origTxIn, tx.vin)
6079 if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
6086 tx.vin.push_back(txin);
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)
6095 uint64_t interest2 = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0;
6096 BOOST_FOREACH (const CRecipient& recipient, vecSend)
6098 if (nValue < 0 || recipient.nAmount < 0)
6100 strFailReason = _("Transaction amounts must be positive");
6103 nValue += recipient.nAmount;
6105 if (recipient.fSubtractFeeFromAmount)
6106 nSubtractFeeFromAmount++;
6108 if (vecSend.empty() || nValue < 0)
6110 strFailReason = _("Transaction amounts must be positive");
6114 wtxNew.fTimeReceivedIsTxTime = true;
6115 wtxNew.BindWallet(this);
6116 int nextBlockHeight = chainActive.Height() + 1;
6118 CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
6119 txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
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.");
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;
6134 // Discourage fee sniping.
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
6144 txNew.nLockTime = std::max(0, chainActive.Height() - 10);
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
6150 if (GetRandInt(10) == 0)
6151 txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
6153 assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
6154 assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
6157 LOCK2(cs_main, cs_wallet);
6165 wtxNew.fFromMe = true;
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)
6176 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
6178 if (recipient.fSubtractFeeFromAmount)
6180 txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
6182 if (fFirst) // first receiver pays the remainder not divisible by output count
6185 txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
6191 if (txout.IsDust(::minRelayTxFee) && !(txout.nValue == 0 && txout.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode != EVAL_NONE))
6193 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
6195 if (txout.nValue < 0)
6196 strFailReason = _("The transaction amount is too small to pay the fee");
6198 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
6201 strFailReason = _("Transaction amount too small");
6204 txNew.vout.push_back(txout);
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;
6213 if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyProtectedCoinbaseCoins, fNeedProtectedCoinbaseCoins, coinControl))
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");
6220 strFailReason = _("Insufficient funds");
6224 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
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 )
6234 interest2 += pcoin.first->vout[pcoin.second].interest;
6235 //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN);
6237 int age = pcoin.first->GetDepthInMainChain();
6240 dPriority += (double)nCredit * age;
6242 //if ( KOMODO_EXCHANGEWALLET != 0 )
6244 //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN);
6245 //interest = 0; // interest2 also
6247 if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 )
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);
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)
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;
6268 // coin control: send change to custom address
6269 if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
6270 scriptChange = GetScriptForDestination(coinControl->destChange);
6272 // no coin control: send change to newly generated address
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.
6282 // Reserve a new key pair from key pool
6284 extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
6285 if ( USE_EXTERNAL_PUBKEY == 0 )
6288 ret = reservekey.GetReservedKey(vchPubKey);
6289 assert(ret); // should never fail, as we just unlocked
6290 scriptChange = GetScriptForDestination(vchPubKey.GetID());
6294 //fprintf(stderr,"use notary pubkey\n");
6295 scriptChange = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
6299 CTxOut newTxOut(nChange, scriptChange);
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))
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
6310 if (vecSend[i].fSubtractFeeFromAmount)
6312 txNew.vout[i].nValue -= nDust;
6313 if (txNew.vout[i].IsDust(::minRelayTxFee))
6315 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
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))
6328 reservekey.ReturnKey();
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);
6336 } else reservekey.ReturnKey();
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));
6346 // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
6347 size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
6350 if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) {
6355 size_t n = txNew.vin.size();
6357 strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
6362 // Grab the current consensus branch ID
6363 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
6367 CTransaction txNewConst(txNew);
6368 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6371 const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
6372 SignatureData sigdata;
6374 signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, scriptPubKey), scriptPubKey, sigdata, consensusBranchId);
6376 signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
6380 strFailReason = _("Signing transaction failed");
6383 UpdateTransaction(txNew, nIn, sigdata);
6389 unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
6391 // Remove scriptSigs if we used dummy signatures for fee calculation
6393 BOOST_FOREACH (CTxIn& vin, txNew.vin)
6394 vin.scriptSig = CScript();
6397 // Embed the constructed transaction data in wtxNew.
6398 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
6401 if (nBytes >= max_tx_size)
6403 strFailReason = _("Transaction too large");
6407 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
6409 // Can we complete this as a free transaction?
6410 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
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))
6418 // Small enough, and priority high enough, to send for free
6419 if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
6423 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
6424 if ( nFeeNeeded < 5000 )
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))
6431 strFailReason = _("Transaction too large for fee policy");
6435 if (nFeeRet >= nFeeNeeded)
6436 break; // Done, enough fee included.
6438 // Include more fee and try again.
6439 nFeeRet = nFeeNeeded;
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)
6456 CCurrencyValueMap totalReserveOutput;
6457 CAmount totalNativeOutput = 0;
6459 CCurrencyValueMap reserveCurrencies;
6460 unsigned int nSubtractFeeFromAmount = 0;
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();
6467 if (ConnectedChains.ReserveCurrencies().size())
6469 for (auto &oneCur : ConnectedChains.ReserveCurrencies())
6471 reserveCurrencies.valueMap[oneCur.first] = 1; // we're only testing for intersection, not value
6476 // make sure we have some outputs
6477 if (vecSend.empty())
6479 strFailReason = _("Transaction must have outputs");
6480 return RPC_INVALID_PARAMETER;
6483 CCurrencyDefinition newCurrency;
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)
6489 if (recipient.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode == EVAL_CURRENCY_DEFINITION && p.vData.size() >= 1)
6491 if (newCurrency.IsValid())
6493 strFailReason = _("A normal transaction cannot define define multiple currencies");
6494 return RPC_INVALID_PARAMETER;
6496 newCurrency = CCurrencyDefinition(p.vData[0]);
6498 CCurrencyValueMap values = recipient.scriptPubKey.ReserveOutValue();
6499 CCurrencyValueMap zeroes = values - values; // zero values of the same currencies
6501 if (!values.IsValid())
6503 strFailReason = _("Output cannot have NULL currency type");
6504 return RPC_INVALID_PARAMETER;
6506 if (values.HasNegative())
6508 strFailReason = _("Transaction output amounts must not be negative");
6509 return RPC_INVALID_PARAMETER;
6512 totalNativeOutput += recipient.nAmount;
6514 totalReserveOutput += values;
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)))
6519 nSubtractFeeFromAmount++;
6521 else if (recipient.fSubtractFeeFromAmount)
6523 strFailReason = _("Cannot specify to subtract fee from amount on non-native, non-reserve currency outputs");
6524 return RPC_INVALID_PARAMETER;
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())
6530 strFailReason = _("Transaction amounts must not be negative");
6531 return RPC_INVALID_PARAMETER;
6535 if (newCurrency.IsValid())
6537 totalReserveOutput.valueMap.erase(newCurrency.GetID());
6540 //printf("totalReserveOutput: %s\n", totalReserveOutput.ToUniValue().write(1,2).c_str());
6542 int nextBlockHeight = chainActive.Height() + 1;
6544 CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight);
6546 std::vector<CTxIn> extraInputs = wtxNew.vin;
6548 wtxNew.fTimeReceivedIsTxTime = true;
6549 wtxNew.BindWallet(this);
6550 txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
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;
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;
6565 // Discourage fee sniping.
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
6575 txNew.nLockTime = std::max(0, chainActive.Height() - 10);
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
6581 if (GetRandInt(10) == 0)
6582 txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
6584 assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
6585 assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
6587 CCurrencyValueMap exchangeRates;
6589 LOCK2(cs_main, cs_wallet);
6591 auto currencyState = ConnectedChains.GetCurrencyState(nextBlockHeight - 1);
6592 for (int i = 0; i < currencyState.currencies.size(); i++)
6594 exchangeRates.valueMap[currencyState.currencies[i]] = currencyState.PriceInReserve(i);
6603 wtxNew.fFromMe = true;
6608 // dust threshold of reserve may be different than native coin, if so, convert
6609 CAmount dustThreshold;
6611 CAmount nTotalNativeValue = totalNativeOutput;
6612 CCurrencyValueMap totalReserveValue = totalReserveOutput;
6614 if (nSubtractFeeFromAmount == 0)
6615 nTotalNativeValue += nFeeRet;
6617 double dPriority = 0;
6618 // vouts to the payees
6619 BOOST_FOREACH (const CRecipient& recipient, vecSend)
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;
6627 // here, if we know that it isn't an opret, it will have an output that expects input
6628 if (!recipient.scriptPubKey.IsOpReturn())
6631 CCurrencyValueMap reserveOutput = recipient.scriptPubKey.ReserveOutValue(p);
6632 CCurrencyValueMap relevantReserves;
6634 if (recipient.fSubtractFeeFromAmount)
6636 CAmount subFee = nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
6638 if (fFirst) // first receiver pays the remainder not divisible by output count
6641 subFee += nFeeRet % nSubtractFeeFromAmount;
6644 if (subFee <= txout.nValue)
6646 txout.nValue -= subFee;
6648 else if ((relevantReserves = reserveOutput.IntersectingValues(reserveCurrencies)).valueMap.size())
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)
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);
6665 txout.scriptPubKey.SetReserveOutValue(reserveOutput);
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;
6676 dustThreshold = txout.GetDustThreshold(::minRelayTxFee);
6678 // only non-crypto condition, and normal reserve outputs are subject to dust limitations
6680 p.evalCode == EVAL_RESERVE_OUTPUT ||
6681 p.evalCode == EVAL_RESERVE_DEPOSIT ||
6682 p.evalCode == EVAL_RESERVE_EXCHANGE ||
6683 p.evalCode == EVAL_NONE)
6685 // add all values to a native equivalent
6686 // reserve currencies have a native value as well
6687 if (exchangeRates.IntersectingValues(reserveOutput).valueMap.size())
6689 nativeEquivalent += currencyState.ReserveToNativeRaw(relevantReserves, exchangeRates.AsCurrencyVector(currencyState.currencies));
6693 nativeEquivalent += reserveOutput.valueMap.size() ? reserveOutput.valueMap.begin()->second : 0;
6696 if (nativeEquivalent < dustThreshold)
6698 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
6700 if (nativeEquivalent < 0)
6701 strFailReason = _("The transaction amount is too small to pay the fee");
6703 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
6706 strFailReason = _("Transaction amount too small");
6707 return RPC_INVALID_PARAMETER;
6711 txNew.vout.push_back(txout);
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;
6721 if (!SelectReserveCoins(totalReserveValue,
6731 strFailReason = _("Insufficient funds");
6732 return RPC_WALLET_INSUFFICIENT_FUNDS;
6736 if (totalValueIn.valueMap.count(ASSETCHAINS_CHAINID))
6738 for (auto oneOut : setCoins)
6740 UniValue oneTxObj(UniValue::VOBJ);
6741 TxToUniv(*oneOut.first, uint256(), oneTxObj);
6742 printf("TRANSACTION\n%s\n", oneTxObj.write(1,2).c_str());
6744 printf("totalValueIn: %s\ntotalReserveValue: %s\n", totalValueIn.ToUniValue().write().c_str(), totalReserveValue.ToUniValue().write().c_str());
6748 std::vector<std::pair<std::pair<const CWalletTx*, unsigned int>, CAmount>> coinsWithEquivalentNative;
6749 if (reserveCurrencies.valueMap.size())
6751 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
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));
6760 CCurrencyValueMap reserveChange = totalValueIn - totalReserveValue;
6762 //printf("reservechange: %s\ntotalvaluein: %s\n", reserveChange.ToUniValue().write(1,2).c_str(), totalValueIn.ToUniValue().write(1,2).c_str());
6764 CCurrencyValueMap convertibleChange = reserveCurrencies.IntersectingValues(reserveChange);
6765 CAmount nChange = totalNativeValueIn - nTotalNativeValue;
6766 CAmount nConvertedReserveChange = 0;
6768 // /printf("tokenChange: %s\nnativeChange: %s\n", reserveChange.ToUniValue().write().c_str(), ValueFromAmount(nChange).write().c_str());
6770 // if we will try to take the fee from change
6771 if (nSubtractFeeFromAmount == 0)
6773 if (nChange < nFeeRet && convertibleChange.valueMap.size())
6775 nConvertedReserveChange = currencyState.ReserveToNativeRaw(convertibleChange,
6776 exchangeRates.AsCurrencyVector(currencyState.currencies));
6781 if ((nChange + nConvertedReserveChange > 0) || (reserveChange > CCurrencyValueMap()))
6783 // if we can and need to convert reserves, adjust reserve change output amounts as needed
6784 if (nChange < 0 && convertibleChange.valueMap.size())
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;
6793 for (int i = 0; i < currencyState.currencies.size(); i++)
6795 auto it = reserveChange.valueMap.find(currencyState.currencies[i]);
6796 if (it != reserveChange.valueMap.end())
6798 CAmount feeAsReserve = currencyState.NativeToReserve(nChangePerCur + (nChangeMod ? 1 : 0), i);
6799 if (it->second - feeAsReserve <= 0)
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);
6808 it->second -= feeAsReserve;
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
6816 for (int i = 0; i < currencyState.currencies.size(); i++)
6818 auto it = reserveChange.valueMap.find(currencyState.currencies[i]);
6819 if (it != reserveChange.valueMap.end())
6821 CAmount feeAsReserve = currencyState.NativeToReserve(remainder, i);
6822 if (it->second - feeAsReserve <= 0)
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);
6831 it->second -= feeAsReserve;
6839 // coin control: send change to custom address
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)
6846 changeDest = coinControl->destChange;
6850 // no coin control: send change to newly generated address
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.
6859 // Reserve a new key pair from key pool
6860 extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
6862 if ( USE_EXTERNAL_PUBKEY != 0 )
6864 //fprintf(stderr,"use notary pubkey\n");
6865 pubKey = CPubKey(ParseHex(NOTARY_PUBKEY));
6866 changeDest = CTxDestination(pubKey);
6868 else if (pOnlyFromDest && pOnlyFromDest->which() == COptCCParams::ADDRTYPE_ID)
6870 changeDest = *pOnlyFromDest;
6875 ret = reservekey.GetReservedKey(pubKey);
6876 assert(ret); // should never fail, as we just unlocked
6877 changeDest = CTxDestination(pubKey);
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)
6890 nChangePosRet = txNew.vout.size() - 1; // dont change first or last
6892 vector<CTxOut>::iterator position = txNew.vout.begin() + nChangePosRet;
6893 txNew.vout.insert(position, CTxOut(nChange, GetScriptForDestination(changeDest)));
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)
6902 assert(curChangeOut.first != ASSETCHAINS_CHAINID);
6903 auto curIt = reserveIndexMap.find(curChangeOut.first);
6904 if (curIt != reserveIndexMap.end())
6906 outVal = currencyState.ReserveToNative(curChangeOut.second, curIt->second);
6910 outVal = curChangeOut.second;
6913 if (outVal >= dustThreshold)
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))));
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())
6926 // if we made no change outputs, return the key
6927 if (!nChangeOutputs)
6929 reservekey.ReturnKey();
6931 } else reservekey.ReturnKey();
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)
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())
6945 setCoins.insert(std::make_pair(&(wit->second), oneIn.prevout.n));
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));
6957 // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
6958 size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
6961 if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) {
6966 size_t n = txNew.vin.size();
6968 strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
6969 return RPC_INVALID_PARAMETER;
6973 // Grab the current consensus branch ID
6974 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
6978 CTransaction txNewConst(txNew);
6979 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
6982 const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
6983 SignatureData sigdata;
6985 signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, scriptPubKey), scriptPubKey, sigdata, consensusBranchId);
6987 signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
6991 strFailReason = _("Signing transaction failed");
6992 return RPC_TRANSACTION_ERROR;
6994 UpdateTransaction(txNew, nIn, sigdata);
7000 unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
7002 // Remove scriptSigs if we used dummy signatures for fee calculation
7004 BOOST_FOREACH (CTxIn& vin, txNew.vin)
7005 vin.scriptSig = CScript();
7008 // Embed the constructed transaction data in wtxNew.
7009 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
7012 if (nBytes >= max_tx_size)
7014 strFailReason = _("Transaction too large");
7015 return RPC_TRANSACTION_ERROR;
7018 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
7020 // Can we complete this as a free transaction?
7021 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
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))
7029 // Small enough, and priority high enough, to send for free
7030 if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
7034 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
7035 if ( nFeeNeeded < 5000 )
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))
7042 strFailReason = _("Transaction too large for fee policy");
7043 return RPC_TRANSACTION_ERROR;
7046 if (nFeeRet >= nFeeNeeded)
7047 break; // Done, enough fee included.
7049 // Include more fee and try again.
7050 nFeeRet = nFeeNeeded;
7058 * Call after CreateTransaction unless you want to abort
7060 bool CWallet::CommitTransaction(CWalletTx& wtxNew, boost::optional<CReserveKey&> reservekey)
7063 LOCK2(cs_main, cs_wallet);
7064 LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
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;
7072 // Take key pair from key pool so it won't be used again
7073 reservekey.get().KeepKey();
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);
7080 // Notify that old coins are spent
7081 set<CWalletTx*> setCoins;
7082 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
7084 CWalletTx &coin = mapWallet[txin.prevout.hash];
7085 coin.BindWallet(this);
7086 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
7093 // Track how many getdata requests our transaction gets
7094 mapRequestCount[wtxNew.GetHash()] = 0;
7096 if (fBroadcastTransactions)
7099 if (!wtxNew.AcceptToMemoryPool(false))
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");
7106 wtxNew.RelayWalletTransaction();
7112 CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
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;
7136 void komodo_prefetch(FILE *fp);
7138 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
7142 fFirstRunRet = false;
7143 if ( 0 ) // doesnt help
7145 fprintf(stderr,"loading wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
7147 if ( (fp= fopen(strWalletFile.c_str(),"rb")) != 0 )
7149 komodo_prefetch(fp);
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)
7158 if (CDB::Rewrite(strWalletFile, "\x04pool"))
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.
7168 if (nLoadWalletRet != DB_LOAD_OK)
7169 return nLoadWalletRet;
7170 fFirstRunRet = !vchDefaultKey.IsValid();
7172 uiInterface.LoadWallet(this);
7178 DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
7182 DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx);
7183 if (nZapWalletTxRet == DB_NEED_REWRITE)
7185 if (CDB::Rewrite(strWalletFile, "\x04pool"))
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.
7195 if (nZapWalletTxRet != DB_LOAD_OK)
7196 return nZapWalletTxRet;
7202 bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
7204 bool fUpdated = false;
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;
7213 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
7214 strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
7217 if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose))
7219 return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName);
7222 bool CWallet::DelAddressBook(const CTxDestination& address)
7225 LOCK(cs_wallet); // mapAddressBook
7229 // Delete destdata tuples associated with address
7230 std::string strAddress = EncodeDestination(address);
7231 BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
7233 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
7236 mapAddressBook.erase(address);
7239 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
7243 CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address));
7244 return CWalletDB(strWalletFile).EraseName(EncodeDestination(address));
7247 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
7251 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
7254 vchDefaultKey = vchPubKey;
7259 * Mark old keypool keys as used,
7260 * and generate all new keys
7262 bool CWallet::NewKeyPool()
7266 CWalletDB walletdb(strWalletFile);
7267 BOOST_FOREACH(int64_t nIndex, setKeyPool)
7268 walletdb.ErasePool(nIndex);
7274 int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
7275 for (int i = 0; i < nKeys; i++)
7277 int64_t nIndex = i+1;
7278 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
7279 setKeyPool.insert(nIndex);
7281 LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
7286 bool CWallet::TopUpKeyPool(unsigned int kpSize)
7294 CWalletDB walletdb(strWalletFile);
7297 unsigned int nTargetSize;
7299 nTargetSize = kpSize;
7301 nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
7303 while (setKeyPool.size() < (nTargetSize + 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());
7317 void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
7320 keypool.vchPubKey = CPubKey();
7327 // Get the oldest key
7328 if(setKeyPool.empty())
7331 CWalletDB walletdb(strWalletFile);
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);
7344 void CWallet::KeepKey(int64_t nIndex)
7346 // Remove from key pool
7349 CWalletDB walletdb(strWalletFile);
7350 walletdb.ErasePool(nIndex);
7352 LogPrintf("keypool keep %d\n", nIndex);
7355 void CWallet::ReturnKey(int64_t nIndex)
7357 // Return to key pool
7360 setKeyPool.insert(nIndex);
7362 //LogPrintf("keypool return %d\n", nIndex);
7365 bool CWallet::GetKeyFromPool(CPubKey& result)
7371 ReserveKeyFromKeyPool(nIndex, keypool);
7374 if (IsLocked()) return false;
7375 result = GenerateNewKey();
7379 result = keypool.vchPubKey;
7384 int64_t CWallet::GetOldestKeyPoolTime()
7388 ReserveKeyFromKeyPool(nIndex, keypool);
7392 return keypool.nTime;
7395 std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
7397 map<CTxDestination, CAmount> balances;
7401 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
7403 CWalletTx *pcoin = &walletEntry.second;
7405 if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
7408 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
7411 int nDepth = pcoin->GetDepthInMainChain();
7412 if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
7415 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
7417 CTxDestination addr;
7418 if (!IsMine(pcoin->vout[i]))
7420 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
7423 CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
7425 if (!balances.count(addr))
7427 balances[addr] += n;
7435 set< set<CTxDestination> > CWallet::GetAddressGroupings()
7437 AssertLockHeld(cs_wallet); // mapWallet
7438 set< set<CTxDestination> > groupings;
7439 set<CTxDestination> grouping;
7441 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
7443 CWalletTx *pcoin = &walletEntry.second;
7445 if (pcoin->vin.size() > 0)
7447 bool any_mine = false;
7448 // group all input addresses with each other
7449 BOOST_FOREACH(CTxIn txin, pcoin->vin)
7451 CTxDestination address;
7452 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
7454 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
7456 grouping.insert(address);
7460 // group change with input addresses
7463 BOOST_FOREACH(CTxOut txout, pcoin->vout)
7464 if (IsChange(txout))
7466 CTxDestination txoutAddr;
7467 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
7469 grouping.insert(txoutAddr);
7472 if (grouping.size() > 0)
7474 groupings.insert(grouping);
7479 // group lone addrs by themselves
7480 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
7481 if (IsMine(pcoin->vout[i]))
7483 CTxDestination address;
7484 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
7486 grouping.insert(address);
7487 groupings.insert(grouping);
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)
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);
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)
7507 merged->insert(hit->begin(), hit->end());
7508 uniqueGroupings.erase(hit);
7511 uniqueGroupings.insert(merged);
7514 BOOST_FOREACH(CTxDestination element, *merged)
7515 setmap[element] = merged;
7518 set< set<CTxDestination> > ret;
7519 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
7521 ret.insert(*uniqueGrouping);
7522 delete uniqueGrouping;
7528 std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
7531 set<CTxDestination> result;
7532 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
7534 const CTxDestination& address = item.first;
7535 const string& strName = item.second.name;
7536 if (strName == strAccount)
7537 result.insert(address);
7542 bool CReserveKey::GetReservedKey(CPubKey& pubkey)
7547 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
7549 vchPubKey = keypool.vchPubKey;
7554 assert(vchPubKey.IsValid());
7559 void CReserveKey::KeepKey()
7562 pwallet->KeepKey(nIndex);
7564 vchPubKey = CPubKey();
7567 void CReserveKey::ReturnKey()
7570 pwallet->ReturnKey(nIndex);
7572 vchPubKey = CPubKey();
7575 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
7579 CWalletDB walletdb(strWalletFile);
7581 LOCK2(cs_main, cs_wallet);
7582 BOOST_FOREACH(const int64_t& id, setKeyPool)
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);
7595 void CWallet::UpdatedTransaction(const uint256 &hashTx)
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);
7606 class MiningAddressScript : public CReserveScript
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() {}
7616 void GetScriptForMiningAddress(boost::shared_ptr<CReserveScript> &script)
7618 CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
7619 if (!IsValidDestination(addr)) {
7623 boost::shared_ptr<MiningAddressScript> mAddr(new MiningAddressScript());
7625 script->reserveScript = GetScriptForDestination(addr);
7628 void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
7630 if (!GetArg("-mineraddress", "").empty())
7632 GetScriptForMiningAddress(script);
7636 boost::shared_ptr<CReserveKey> rKey(new CReserveKey(this));
7638 if (!rKey->GetReservedKey(pubkey))
7642 script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
7645 void CWallet::LockCoin(COutPoint& output)
7647 AssertLockHeld(cs_wallet); // setLockedCoins
7648 setLockedCoins.insert(output);
7651 void CWallet::UnlockCoin(COutPoint& output)
7653 AssertLockHeld(cs_wallet); // setLockedCoins
7654 setLockedCoins.erase(output);
7657 void CWallet::UnlockAllCoins()
7659 AssertLockHeld(cs_wallet); // setLockedCoins
7660 setLockedCoins.clear();
7663 bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
7665 AssertLockHeld(cs_wallet); // setLockedCoins
7666 COutPoint outpt(hash, n);
7668 return (setLockedCoins.count(outpt) > 0);
7671 void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
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);
7682 // Note Locking Operations
7684 void CWallet::LockNote(const JSOutPoint& output)
7686 AssertLockHeld(cs_wallet); // setLockedSproutNotes
7687 setLockedSproutNotes.insert(output);
7690 void CWallet::UnlockNote(const JSOutPoint& output)
7692 AssertLockHeld(cs_wallet); // setLockedSproutNotes
7693 setLockedSproutNotes.erase(output);
7696 void CWallet::UnlockAllSproutNotes()
7698 AssertLockHeld(cs_wallet); // setLockedSproutNotes
7699 setLockedSproutNotes.clear();
7702 bool CWallet::IsLockedNote(const JSOutPoint& outpt) const
7704 AssertLockHeld(cs_wallet); // setLockedSproutNotes
7706 return (setLockedSproutNotes.count(outpt) > 0);
7709 std::vector<JSOutPoint> CWallet::ListLockedSproutNotes()
7711 AssertLockHeld(cs_wallet); // setLockedSproutNotes
7712 std::vector<JSOutPoint> vOutpts(setLockedSproutNotes.begin(), setLockedSproutNotes.end());
7716 void CWallet::LockNote(const SaplingOutPoint& output)
7718 AssertLockHeld(cs_wallet);
7719 setLockedSaplingNotes.insert(output);
7722 void CWallet::UnlockNote(const SaplingOutPoint& output)
7724 AssertLockHeld(cs_wallet);
7725 setLockedSaplingNotes.erase(output);
7728 void CWallet::UnlockAllSaplingNotes()
7730 AssertLockHeld(cs_wallet);
7731 setLockedSaplingNotes.clear();
7734 bool CWallet::IsLockedNote(const SaplingOutPoint& output) const
7736 AssertLockHeld(cs_wallet);
7737 return (setLockedSaplingNotes.count(output) > 0);
7740 std::vector<SaplingOutPoint> CWallet::ListLockedSaplingNotes()
7742 AssertLockHeld(cs_wallet);
7743 std::vector<SaplingOutPoint> vOutputs(setLockedSaplingNotes.begin(), setLockedSaplingNotes.end());
7747 /** @} */ // end of Actions
7749 class CAffectedKeysVisitor : public boost::static_visitor<void> {
7751 const CKeyStore &keystore;
7752 std::vector<CKeyID> &vKeys;
7755 CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
7757 void Process(const CScript &script) {
7759 std::vector<CTxDestination> vDest;
7761 if (ExtractDestinations(script, type, vDest, nRequired)) {
7762 BOOST_FOREACH(const CTxDestination &dest, vDest)
7763 boost::apply_visitor(*this, dest);
7767 void operator()(const CKeyID &keyId) {
7768 if (keystore.HaveKey(keyId))
7769 vKeys.push_back(keyId);
7772 void operator()(const CPubKey &key) {
7773 CKeyID keyId = key.GetID();
7774 if (keystore.HaveKey(keyId))
7775 vKeys.push_back(keyId);
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);
7784 void operator()(const CIndexID &keyId) {
7787 void operator()(const CScriptID &scriptId) {
7789 if (keystore.GetCScript(scriptId, script))
7793 void operator()(const CIdentityID &idId) {
7794 std::pair<CIdentityMapKey, CIdentityMapValue> identity;
7795 if (keystore.GetIdentity(idId, identity))
7797 for (auto dest : identity.second.primaryAddresses)
7799 boost::apply_visitor(*this, dest);
7804 void operator()(const CNoDestination &none) {}
7807 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
7808 AssertLockHeld(cs_wallet); // mapKeyMetadata
7809 mapKeyBirth.clear();
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;
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;
7821 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
7822 if (mapKeyBirth.count(keyid) == 0)
7823 mapKeyFirstBlock[keyid] = pindexMax;
7827 // if there are no such keys, we're done
7828 if (mapKeyFirstBlock.empty())
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;
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
7859 bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
7861 if (boost::get<CNoDestination>(&dest))
7864 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
7867 return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value);
7870 bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
7872 if (!mapAddressBook[dest].destdata.erase(key))
7876 return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key);
7879 bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
7881 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
7885 bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
7887 std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
7888 if(i != mapAddressBook.end())
7890 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
7891 if(j != i->second.destdata.end())
7901 CKeyPool::CKeyPool()
7906 CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
7909 vchPubKey = vchPubKeyIn;
7912 CWalletKey::CWalletKey(int64_t nExpires)
7914 nTimeCreated = (nExpires ? GetTime() : 0);
7915 nTimeExpires = nExpires;
7918 void CMerkleTx::SetMerkleBranch(const CBlock& block)
7922 // Update the tx's hashBlock
7923 hashBlock = block.GetHash();
7925 // Locate the transaction
7926 for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
7927 if (block.vtx[nIndex] == *(CTransaction*)this)
7929 if (nIndex == (int)block.vtx.size())
7931 vMerkleBranch.clear();
7933 LogPrintf("ERROR: %s: couldn't find tx (%s) in block (%s)\n", __func__, GetHash().GetHex().c_str(), hashBlock.GetHex().c_str());
7936 // Fill in merkle branch
7937 vMerkleBranch = block.GetMerkleBranch(nIndex);
7940 int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
7942 if (hashBlock.IsNull() || nIndex == -1)
7944 AssertLockHeld(cs_main);
7946 // Find the block it claims to be in
7947 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
7948 if (mi == mapBlockIndex.end())
7950 CBlockIndex* pindex = (*mi).second;
7951 if (!pindex || !chainActive.Contains(pindex))
7954 // Make sure the merkle branch connects to this block
7955 if (!fMerkleVerified)
7957 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
7959 fMerkleVerified = true;
7963 return chainActive.Height() - pindex->GetHeight() + 1;
7966 int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
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
7976 int CMerkleTx::GetBlocksToMaturity() const
7978 if ( ASSETCHAINS_SYMBOL[0] == 0 )
7979 COINBASE_MATURITY = _COINBASE_MATURITY;
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);
7990 bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
7992 CValidationState state;
7993 return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
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.
8000 void CWallet::GetFilteredNotes(
8001 std::vector<SproutNoteEntry>& sproutEntries,
8002 std::vector<SaplingNoteEntry>& saplingEntries,
8003 std::string address,
8006 bool requireSpendingKey)
8008 std::set<PaymentAddress> filterAddresses;
8010 if (address.length() > 0) {
8011 filterAddresses.insert(DecodePaymentAddress(address));
8014 GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey);
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.
8022 void CWallet::GetFilteredNotes(
8023 std::vector<SproutNoteEntry>& sproutEntries,
8024 std::vector<SaplingNoteEntry>& saplingEntries,
8025 std::set<PaymentAddress>& filterAddresses,
8029 bool requireSpendingKey,
8032 LOCK2(cs_main, cs_wallet);
8034 for (auto & p : mapWallet) {
8035 CWalletTx wtx = p.second;
8037 // Filter the transactions before checking for notes
8038 if (!CheckFinalTx(wtx) ||
8039 wtx.GetBlocksToMaturity() > 0 ||
8040 wtx.GetDepthInMainChain() < minDepth ||
8041 wtx.GetDepthInMainChain() > maxDepth) {
8045 for (auto & pair : wtx.mapSproutNoteData) {
8046 JSOutPoint jsop = pair.first;
8047 SproutNoteData nd = pair.second;
8048 SproutPaymentAddress pa = nd.address;
8050 // skip notes which belong to a different payment address in the wallet
8051 if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
8055 // skip note which has been spent
8056 if (ignoreSpent && nd.nullifier && IsSproutSpent(*nd.nullifier)) {
8060 // skip notes which cannot be spent
8061 if (requireSpendingKey && !HaveSproutSpendingKey(pa)) {
8065 // skip locked notes
8066 if (ignoreLocked && IsLockedNote(jsop)) {
8070 int i = jsop.js; // Index into CTransaction.vJoinSplit
8071 int j = jsop.n; // Index into JSDescription.ciphertexts
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)));
8080 // determine amount of funds in the note
8081 auto hSig = wtx.vJoinSplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
8083 SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
8085 wtx.vJoinSplit[i].ciphertexts[j],
8086 wtx.vJoinSplit[i].ephemeralKey,
8090 sproutEntries.push_back(SproutNoteEntry {
8091 jsop, pa, plaintext.note(pa), plaintext.memo(), wtx.GetDepthInMainChain() });
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()));
8102 for (auto & pair : wtx.mapSaplingNoteData) {
8103 SaplingOutPoint op = pair.first;
8104 SaplingNoteData nd = pair.second;
8106 auto maybe_pt = SaplingNotePlaintext::decrypt(
8107 wtx.vShieldedOutput[op.n].encCiphertext,
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();
8114 auto maybe_pa = nd.ivk.address(notePt.d);
8115 assert(static_cast<bool>(maybe_pa));
8116 auto pa = maybe_pa.get();
8118 // skip notes which belong to a different payment address in the wallet
8119 if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
8123 if (ignoreSpent && nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
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))) {
8138 // skip locked notes
8139 if (ignoreLocked && IsLockedNote(op)) {
8143 auto note = notePt.note(nd.ivk).get();
8144 saplingEntries.push_back(SaplingNoteEntry {
8145 op, pa, note, notePt.memo(), wtx.GetDepthInMainChain() });
8152 // Shielded key and address generalizations
8155 bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const
8157 return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr);
8160 bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
8162 libzcash::SaplingIncomingViewingKey ivk;
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);
8170 bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
8175 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const
8177 return m_wallet->HaveSproutSpendingKey(zaddr);
8180 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
8182 libzcash::SaplingIncomingViewingKey ivk;
8183 libzcash::SaplingFullViewingKey fvk;
8185 return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
8186 m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
8187 m_wallet->HaveSaplingSpendingKey(fvk);
8190 bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncoding& no) const
8195 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8196 const libzcash::SproutPaymentAddress &zaddr) const
8198 libzcash::SproutSpendingKey k;
8199 if (m_wallet->GetSproutSpendingKey(zaddr, k)) {
8200 return libzcash::SpendingKey(k);
8206 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8207 const libzcash::SaplingPaymentAddress &zaddr) const
8209 libzcash::SaplingExtendedSpendingKey extsk;
8210 if (m_wallet->GetSaplingExtendedSpendingKey(zaddr, extsk)) {
8211 return libzcash::SpendingKey(extsk);
8217 boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
8218 const libzcash::InvalidEncoding& no) const
8220 // Defaults to InvalidEncoding
8221 return libzcash::SpendingKey();
8224 SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
8225 auto addr = sk.address();
8227 LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
8229 if (m_wallet->HaveSproutSpendingKey(addr)) {
8230 return KeyAlreadyExists;
8231 } else if (m_wallet-> AddSproutZKey(sk)) {
8232 m_wallet->mapSproutZKeyMetadata[addr].nCreateTime = nTime;
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();
8245 LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
8247 // Don't throw error in case a key is already there
8248 if (m_wallet->HaveSaplingSpendingKey(fvk)) {
8249 return KeyAlreadyExists;
8251 if (!m_wallet-> AddSaplingZKey(sk, addr)) {
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;
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);
8263 m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
8267 seedFp.SetHex(seedFpStr.get());
8268 m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
8275 SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
8276 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");