]> Git Repo - VerusCoin.git/blame - src/wallet/wallet.cpp
Ability to define, list, start and connect to PBaaS chains
[VerusCoin.git] / src / wallet / wallet.cpp
CommitLineData
b2120e22 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
5b40d886 3// Distributed under the MIT software license, see the accompanying
3a25a2b9 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
e8ef3da7 5
50c72f23 6#include "wallet/wallet.h"
51ed9ec9 7
3e1cf9b6 8#include "checkpoints.h"
6a86c24d 9#include "coincontrol.h"
be126699 10#include "consensus/upgrades.h"
da29ecbc 11#include "consensus/validation.h"
9bb37bf0 12#include "consensus/consensus.h"
02e67455 13#include "init.h"
3d31e09c 14#include "key_io.h"
8a893c94 15#include "main.h"
b2a98c42 16#include "mmr.h"
0689f46c 17#include "net.h"
fcab001b 18#include "rpc/protocol.h"
e088d65a 19#include "script/script.h"
20#include "script/sign.h"
14f888ca 21#include "timedata.h"
ad49c256 22#include "utilmoneystr.h"
02e67455 23#include "zcash/Note.hpp"
73699cea 24#include "crypter.h"
4a4e912b 25#include "coins.h"
70b4ad2d 26#include "zcash/zip32.h"
ca4a5f26 27#include "cc/StakeGuard.h"
1fae37f6 28
d0c4197e
PK
29#include <assert.h>
30
cae686d3 31#include <boost/algorithm/string/replace.hpp>
2bb1c877 32#include <boost/filesystem.hpp>
ad49c256 33#include <boost/thread.hpp>
e8ef3da7
WL
34
35using namespace std;
c1c45943 36using namespace libzcash;
e8ef3da7 37
5b40d886
MF
38/**
39 * Settings
40 */
c6cb21d1 41CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
aa279d61 42CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
77ed59df 43unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
1bbca249 44bool bSpendZeroConfChange = true;
c1c9d5b4 45bool fSendFreeTransactions = false;
ed3e5e46 46bool fPayAtLeastCustomFee = true;
bdc72415 47#include "komodo_defs.h"
48
06f41160 49extern int32_t USE_EXTERNAL_PUBKEY;
50extern std::string NOTARY_PUBKEY;
6ad13d7c 51extern int32_t KOMODO_EXCHANGEWALLET;
7c130297 52extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
b2a98c42 53extern uint160 ASSETCHAINS_CHAINID;
1fae37f6 54extern int32_t VERUS_MIN_STAKEAGE;
1f722359 55CBlockIndex *komodo_chainactive(int32_t height);
a55973ae 56extern std::string DONATION_PUBKEY;
e8ef3da7 57
7e6d23b1
CD
58/**
59 * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
5b40d886
MF
60 * Override with -mintxfee
61 */
9b1627d1 62CFeeRate CWallet::minTxFee = CFeeRate(1000);
13fc83c7 63
5b40d886
MF
64/** @defgroup mapWallet
65 *
66 * @{
67 */
e8ef3da7 68
d650f96d
CM
69struct CompareValueOnly
70{
a372168e
MF
71 bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
72 const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
d650f96d
CM
73 {
74 return t1.first < t2.first;
75 }
76};
77
02e67455
JG
78std::string JSOutPoint::ToString() const
79{
80 return strprintf("JSOutPoint(%s, %d, %d)", hash.ToString().substr(0,10), js, n);
81}
82
ad49c256
WL
83std::string COutput::ToString() const
84{
805344dc 85 return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
ad49c256
WL
86}
87
93a18a36
GA
88const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
89{
90 LOCK(cs_wallet);
91 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
92 if (it == mapWallet.end())
93 return NULL;
94 return &(it->second);
95}
96
c1c45943 97// Generate a new spending key and return its public payment address
d6ad8cef 98libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey()
c1c45943 99{
d6b31d59 100 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
d6ad8cef 101
e5eab182 102 auto k = SproutSpendingKey::random();
c1c45943
S
103 auto addr = k.address();
104
105 // Check for collision, even though it is unlikely to ever occur
25d5e80c 106 if (CCryptoKeyStore::HaveSproutSpendingKey(addr))
92fc29a3 107 throw std::runtime_error("CWallet::GenerateNewSproutZKey(): Collision detected");
c1c45943
S
108
109 // Create new metadata
110 int64_t nCreationTime = GetTime();
d6b31d59 111 mapSproutZKeyMetadata[addr] = CKeyMetadata(nCreationTime);
c1c45943 112
a0783bb9 113 if (!AddSproutZKey(k))
92fc29a3 114 throw std::runtime_error("CWallet::GenerateNewSproutZKey(): AddSproutZKey failed");
80ed13d5 115 return addr;
c1c45943
S
116}
117
efb7662d
JG
118// Generate a new Sapling spending key and return its public payment address
119SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
120{
8e91ebf7 121 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
70b4ad2d 122
f82a864d
JG
123 // Create new metadata
124 int64_t nCreationTime = GetTime();
70b4ad2d
JG
125 CKeyMetadata metadata(nCreationTime);
126
127 // Try to get the seed
128 HDSeed seed;
129 if (!GetHDSeed(seed))
130 throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
131
132 auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
b6d1af89 133 uint32_t bip44CoinType = Params().BIP44CoinType();
70b4ad2d
JG
134
135 // We use a fixed keypath scheme of m/32'/coin_type'/account'
136 // Derive m/32'
137 auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
138 // Derive m/32'/coin_type'
b6d1af89 139 auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT);
70b4ad2d
JG
140
141 // Derive account key at next index, skip keys already known to the wallet
142 libzcash::SaplingExtendedSpendingKey xsk;
143 do
144 {
145 xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT);
b6d1af89
JS
146 metadata.hdKeypath = "m/32'/" + std::to_string(bip44CoinType) + "'/" + std::to_string(hdChain.saplingAccountCounter) + "'";
147 metadata.seedFp = hdChain.seedFp;
70b4ad2d
JG
148 // Increment childkey index
149 hdChain.saplingAccountCounter++;
150 } while (HaveSaplingSpendingKey(xsk.expsk.full_viewing_key()));
151
152 // Update the chain model in the database
153 if (fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(hdChain))
154 throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Writing HD chain model failed");
155
156 auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
157 mapSaplingZKeyMetadata[ivk] = metadata;
a4ac4fc3 158
70b4ad2d
JG
159 auto addr = xsk.DefaultAddress();
160 if (!AddSaplingZKey(xsk, addr)) {
f82a864d 161 throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
efb7662d 162 }
f82a864d
JG
163 // return default sapling payment address.
164 return addr;
efb7662d
JG
165}
166
167// Add spending key to keystore
5175a7f0 168bool CWallet::AddSaplingZKey(
70b4ad2d 169 const libzcash::SaplingExtendedSpendingKey &sk,
83c4e360 170 const libzcash::SaplingPaymentAddress &defaultAddr)
efb7662d
JG
171{
172 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
efb7662d 173
5175a7f0 174 if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
efb7662d
JG
175 return false;
176 }
f4207d0c
JG
177
178 if (!fFileBacked) {
179 return true;
180 }
efb7662d 181
c2dc091e 182 if (!IsCrypted()) {
183 auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
184 return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
185 }
f82a864d 186
efb7662d
JG
187 return true;
188}
189
c2dc091e 190// Add payment address -> incoming viewing key map entry
191bool CWallet::AddSaplingIncomingViewingKey(
192 const libzcash::SaplingIncomingViewingKey &ivk,
193 const libzcash::SaplingPaymentAddress &addr)
194{
195 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
196
197 if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
198 return false;
199 }
200
201 if (!fFileBacked) {
202 return true;
203 }
204
205 if (!IsCrypted()) {
206 return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
207 }
208
209 return true;
210}
211
efb7662d 212
c1c45943 213// Add spending key to keystore and persist to disk
a0783bb9 214bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key)
c1c45943 215{
d6b31d59 216 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
c1c45943
S
217 auto addr = key.address();
218
25d5e80c 219 if (!CCryptoKeyStore::AddSproutSpendingKey(key))
c1c45943
S
220 return false;
221
167cd333 222 // check if we need to remove from viewing keys
4c775177
JG
223 if (HaveSproutViewingKey(addr))
224 RemoveSproutViewingKey(key.viewing_key());
167cd333 225
c1c45943
S
226 if (!fFileBacked)
227 return true;
228
229 if (!IsCrypted()) {
230 return CWalletDB(strWalletFile).WriteZKey(addr,
231 key,
d6b31d59 232 mapSproutZKeyMetadata[addr]);
c1c45943
S
233 }
234 return true;
235}
236
fd61d6f5 237CPubKey CWallet::GenerateNewKey()
9976cf07 238{
95691680 239 AssertLockHeld(cs_wallet); // mapKeyMetadata
439e1497 240 bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
38067c18 241
dfa23b94
PW
242 CKey secret;
243 secret.MakeNewKey(fCompressed);
38067c18
PW
244
245 // Compressed public keys were introduced in version 0.6.0
246 if (fCompressed)
439e1497 247 SetMinVersion(FEATURE_COMPRPUBKEY);
38067c18 248
dfa23b94 249 CPubKey pubkey = secret.GetPubKey();
d0c41a73 250 assert(secret.VerifyPubKey(pubkey));
4addb2c0
PW
251
252 // Create new metadata
51ed9ec9 253 int64_t nCreationTime = GetTime();
4addb2c0
PW
254 mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
255 if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
256 nTimeFirstKey = nCreationTime;
257
dfa23b94 258 if (!AddKeyPubKey(secret, pubkey))
5262fde0 259 throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
dfa23b94 260 return pubkey;
9976cf07 261}
e8ef3da7 262
4addb2c0 263bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
e8ef3da7 264{
95691680 265 AssertLockHeld(cs_wallet); // mapKeyMetadata
dfa23b94 266 if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
acd65016 267 return false;
ccca27a7
CL
268
269 // check if we need to remove from watch-only
270 CScript script;
271 script = GetScriptForDestination(pubkey.GetID());
272 if (HaveWatchOnly(script))
273 RemoveWatchOnly(script);
274
e8ef3da7
WL
275 if (!fFileBacked)
276 return true;
dfa23b94 277 if (!IsCrypted()) {
3869fb89
JG
278 return CWalletDB(strWalletFile).WriteKey(pubkey,
279 secret.GetPrivKey(),
4addb2c0 280 mapKeyMetadata[pubkey.GetID()]);
dfa23b94 281 }
84c3c2eb 282 return true;
4e87d341
MC
283}
284
3869fb89 285bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
4addb2c0 286 const vector<unsigned char> &vchCryptedSecret)
4e87d341 287{
efb7662d 288
4e87d341
MC
289 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
290 return false;
291 if (!fFileBacked)
292 return true;
96f34cd5 293 {
f8dcd5ca 294 LOCK(cs_wallet);
96f34cd5 295 if (pwalletdbEncryption)
3869fb89
JG
296 return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
297 vchCryptedSecret,
4addb2c0 298 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 299 else
3869fb89
JG
300 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
301 vchCryptedSecret,
4addb2c0 302 mapKeyMetadata[vchPubKey.GetID()]);
96f34cd5 303 }
0767e691 304 return false;
4e87d341
MC
305}
306
73699cea 307
25d5e80c
JG
308bool CWallet::AddCryptedSproutSpendingKey(
309 const libzcash::SproutPaymentAddress &address,
310 const libzcash::ReceivingKey &rk,
311 const std::vector<unsigned char> &vchCryptedSecret)
73699cea 312{
25d5e80c 313 if (!CCryptoKeyStore::AddCryptedSproutSpendingKey(address, rk, vchCryptedSecret))
73699cea
S
314 return false;
315 if (!fFileBacked)
316 return true;
317 {
318 LOCK(cs_wallet);
82bd9ee8 319 if (pwalletdbEncryption) {
73699cea 320 return pwalletdbEncryption->WriteCryptedZKey(address,
642a1caf 321 rk,
73699cea 322 vchCryptedSecret,
d6b31d59 323 mapSproutZKeyMetadata[address]);
82bd9ee8 324 } else {
73699cea 325 return CWalletDB(strWalletFile).WriteCryptedZKey(address,
642a1caf 326 rk,
73699cea 327 vchCryptedSecret,
d6b31d59 328 mapSproutZKeyMetadata[address]);
82bd9ee8 329 }
73699cea
S
330 }
331 return false;
332}
333
c2dc091e 334bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
5175a7f0 335 const std::vector<unsigned char> &vchCryptedSecret,
83c4e360 336 const libzcash::SaplingPaymentAddress &defaultAddr)
bc6344b3 337{
c2dc091e 338 if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
bc6344b3
JG
339 return false;
340 if (!fFileBacked)
341 return true;
342 {
c2dc091e 343 LOCK(cs_wallet);
344 if (pwalletdbEncryption) {
345 return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
346 vchCryptedSecret,
347 mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
348 } else {
349 return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
350 vchCryptedSecret,
351 mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
352 }
bc6344b3
JG
353 }
354 return false;
355}
356
4addb2c0
PW
357bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
358{
95691680 359 AssertLockHeld(cs_wallet); // mapKeyMetadata
4addb2c0
PW
360 if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
361 nTimeFirstKey = meta.nCreateTime;
362
363 mapKeyMetadata[pubkey.GetID()] = meta;
364 return true;
365}
366
e5eab182 367bool CWallet::LoadZKeyMetadata(const SproutPaymentAddress &addr, const CKeyMetadata &meta)
c1c45943 368{
d6b31d59
EOW
369 AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata
370 mapSproutZKeyMetadata[addr] = meta;
c1c45943
S
371 return true;
372}
373
2f15e86a
GA
374bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
375{
376 return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
377}
378
e5eab182 379bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret)
73699cea 380{
25d5e80c 381 return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret);
73699cea
S
382}
383
c2dc091e 384bool CWallet::LoadCryptedSaplingZKey(
385 const libzcash::SaplingExtendedFullViewingKey &extfvk,
386 const std::vector<unsigned char> &vchCryptedSecret)
387{
388 return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
389}
390
391bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
392{
393 AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
394 mapSaplingZKeyMetadata[ivk] = meta;
395 return true;
396}
397
398bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
399{
400 return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
401}
402
403bool CWallet::LoadSaplingPaymentAddress(
404 const libzcash::SaplingPaymentAddress &addr,
405 const libzcash::SaplingIncomingViewingKey &ivk)
406{
407 return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
408}
409
e5eab182 410bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
c1c45943 411{
25d5e80c 412 return CCryptoKeyStore::AddSproutSpendingKey(key);
c1c45943
S
413}
414
4c775177 415bool CWallet::AddSproutViewingKey(const libzcash::SproutViewingKey &vk)
167cd333 416{
4c775177 417 if (!CCryptoKeyStore::AddSproutViewingKey(vk)) {
167cd333 418 return false;
bec22351 419 }
167cd333 420 nTimeFirstKey = 1; // No birthday information for viewing keys.
bec22351 421 if (!fFileBacked) {
167cd333 422 return true;
bec22351 423 }
4c775177 424 return CWalletDB(strWalletFile).WriteSproutViewingKey(vk);
167cd333
JG
425}
426
4c775177 427bool CWallet::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk)
167cd333
JG
428{
429 AssertLockHeld(cs_wallet);
4c775177 430 if (!CCryptoKeyStore::RemoveSproutViewingKey(vk)) {
167cd333 431 return false;
bec22351
JG
432 }
433 if (fFileBacked) {
4c775177 434 if (!CWalletDB(strWalletFile).EraseSproutViewingKey(vk)) {
167cd333 435 return false;
bec22351
JG
436 }
437 }
167cd333
JG
438
439 return true;
440}
441
4c775177 442bool CWallet::LoadSproutViewingKey(const libzcash::SproutViewingKey &vk)
167cd333 443{
4c775177 444 return CCryptoKeyStore::AddSproutViewingKey(vk);
167cd333
JG
445}
446
922e8e29 447bool CWallet::AddCScript(const CScript& redeemScript)
e679ec96 448{
922e8e29 449 if (!CCryptoKeyStore::AddCScript(redeemScript))
e679ec96
GA
450 return false;
451 if (!fFileBacked)
452 return true;
922e8e29 453 return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
e679ec96
GA
454}
455
18116b06
WL
456bool CWallet::LoadCScript(const CScript& redeemScript)
457{
458 /* A sanity check was added in pull #3843 to avoid adding redeemScripts
459 * that never can be redeemed. However, old wallets may still contain
460 * these. Do not add them to the wallet and warn. */
461 if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
462 {
07444da1 463 std::string strAddr = EncodeDestination(CScriptID(redeemScript));
18116b06
WL
464 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",
465 __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
466 return true;
467 }
468
469 return CCryptoKeyStore::AddCScript(redeemScript);
470}
471
d5087d1b 472bool CWallet::AddWatchOnly(const CScript &dest)
c8988460
PW
473{
474 if (!CCryptoKeyStore::AddWatchOnly(dest))
475 return false;
476 nTimeFirstKey = 1; // No birthday information for watch-only keys.
939ed973 477 NotifyWatchonlyChanged(true);
c8988460
PW
478 if (!fFileBacked)
479 return true;
480 return CWalletDB(strWalletFile).WriteWatchOnly(dest);
481}
482
ccca27a7
CL
483bool CWallet::RemoveWatchOnly(const CScript &dest)
484{
485 AssertLockHeld(cs_wallet);
486 if (!CCryptoKeyStore::RemoveWatchOnly(dest))
487 return false;
488 if (!HaveWatchOnly())
489 NotifyWatchonlyChanged(false);
490 if (fFileBacked)
491 if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
492 return false;
493
494 return true;
495}
496
d5087d1b 497bool CWallet::LoadWatchOnly(const CScript &dest)
c8988460 498{
c8988460
PW
499 return CCryptoKeyStore::AddWatchOnly(dest);
500}
501
94f778bd 502bool CWallet::Unlock(const SecureString& strWalletPassphrase)
4e87d341 503{
6cc4a62c
GA
504 CCrypter crypter;
505 CKeyingMaterial vMasterKey;
4e87d341 506
f8dcd5ca
PW
507 {
508 LOCK(cs_wallet);
4e87d341
MC
509 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
510 {
511 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
512 return false;
513 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
92f2c1fe 514 continue; // try another master key
4e87d341
MC
515 if (CCryptoKeyStore::Unlock(vMasterKey))
516 return true;
517 }
f8dcd5ca 518 }
4e87d341
MC
519 return false;
520}
521
94f778bd 522bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
4e87d341 523{
6cc4a62c 524 bool fWasLocked = IsLocked();
4e87d341 525
6cc4a62c 526 {
f8dcd5ca 527 LOCK(cs_wallet);
4e87d341
MC
528 Lock();
529
530 CCrypter crypter;
531 CKeyingMaterial vMasterKey;
532 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
533 {
534 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
535 return false;
6cc4a62c 536 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
4e87d341
MC
537 return false;
538 if (CCryptoKeyStore::Unlock(vMasterKey))
539 {
51ed9ec9 540 int64_t nStartTime = GetTimeMillis();
ddebdd9a
MC
541 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
542 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
543
544 nStartTime = GetTimeMillis();
545 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
546 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
547
548 if (pMasterKey.second.nDeriveIterations < 25000)
549 pMasterKey.second.nDeriveIterations = 25000;
550
881a85a2 551 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
ddebdd9a 552
4e87d341
MC
553 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
554 return false;
555 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
556 return false;
557 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
558 if (fWasLocked)
559 Lock();
560 return true;
561 }
562 }
563 }
6cc4a62c 564
4e87d341
MC
565 return false;
566}
567
f86ee1c2
EOW
568void CWallet::ChainTip(const CBlockIndex *pindex,
569 const CBlock *pblock,
4fc309f0
EOW
570 SproutMerkleTree sproutTree,
571 SaplingMerkleTree saplingTree,
f86ee1c2 572 bool added)
769e031c
JG
573{
574 if (added) {
f86ee1c2 575 IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree);
769e031c 576 } else {
40ef121e 577 DecrementNoteWitnesses(pindex);
769e031c 578 }
c343e2db 579 UpdateSaplingNullifierNoteMapForBlock(pblock);
769e031c
JG
580}
581
ed6d0b5f
PW
582void CWallet::SetBestChain(const CBlockLocator& loc)
583{
584 CWalletDB walletdb(strWalletFile);
03f83b9b 585 SetBestChainINTERNAL(walletdb, loc);
ed6d0b5f 586}
7414733b 587
e4f0d6a8
LR
588std::set<std::pair<libzcash::PaymentAddress, uint256>> CWallet::GetNullifiersForAddresses(
589 const std::set<libzcash::PaymentAddress> & addresses)
0646f749
EOW
590{
591 std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet;
e4f0d6a8
LR
592 // Sapling ivk -> list of addrs map
593 // (There may be more than one diversified address for a given ivk.)
594 std::map<libzcash::SaplingIncomingViewingKey, std::vector<libzcash::SaplingPaymentAddress>> ivkMap;
595 for (const auto & addr : addresses) {
596 auto saplingAddr = boost::get<libzcash::SaplingPaymentAddress>(&addr);
597 if (saplingAddr != nullptr) {
598 libzcash::SaplingIncomingViewingKey ivk;
599 this->GetSaplingIncomingViewingKey(*saplingAddr, ivk);
600 ivkMap[ivk].push_back(*saplingAddr);
601 }
602 }
0646f749 603 for (const auto & txPair : mapWallet) {
e4f0d6a8 604 // Sprout
2f0b2a25 605 for (const auto & noteDataPair : txPair.second.mapSproutNoteData) {
e4f0d6a8
LR
606 auto & noteData = noteDataPair.second;
607 auto & nullifier = noteData.nullifier;
608 auto & address = noteData.address;
609 if (nullifier && addresses.count(address)) {
610 nullifierSet.insert(std::make_pair(address, nullifier.get()));
611 }
612 }
613 // Sapling
614 for (const auto & noteDataPair : txPair.second.mapSaplingNoteData) {
615 auto & noteData = noteDataPair.second;
616 auto & nullifier = noteData.nullifier;
617 auto & ivk = noteData.ivk;
618 if (nullifier && ivkMap.count(ivk)) {
619 for (const auto & addr : ivkMap[ivk]) {
620 nullifierSet.insert(std::make_pair(addr, nullifier.get()));
621 }
0646f749
EOW
622 }
623 }
624 }
625 return nullifierSet;
626}
627
e4f0d6a8
LR
628bool CWallet::IsNoteSproutChange(
629 const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
630 const PaymentAddress & address,
631 const JSOutPoint & jsop)
0646f749
EOW
632{
633 // A Note is marked as "change" if the address that received it
634 // also spent Notes in the same transaction. This will catch,
635 // for instance:
636 // - Change created by spending fractions of Notes (because
637 // z_sendmany sends change to the originating z-address).
638 // - "Chaining Notes" used to connect JoinSplits together.
639 // - Notes created by consolidation transactions (e.g. using
640 // z_mergetoaddress).
641 // - Notes sent from one address to itself.
642 for (const JSDescription & jsd : mapWallet[jsop.hash].vjoinsplit) {
643 for (const uint256 & nullifier : jsd.nullifiers) {
644 if (nullifierSet.count(std::make_pair(address, nullifier))) {
645 return true;
646 }
647 }
648 }
649 return false;
650}
651
e4f0d6a8
LR
652bool CWallet::IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
653 const libzcash::PaymentAddress & address,
654 const SaplingOutPoint & op)
655{
656 // A Note is marked as "change" if the address that received it
657 // also spent Notes in the same transaction. This will catch,
658 // for instance:
659 // - Change created by spending fractions of Notes (because
660 // z_sendmany sends change to the originating z-address).
661 // - Notes created by consolidation transactions (e.g. using
662 // z_mergetoaddress).
663 // - Notes sent from one address to itself.
664 for (const SpendDescription &spend : mapWallet[op.hash].vShieldedSpend) {
665 if (nullifierSet.count(std::make_pair(address, spend.nullifier))) {
666 return true;
667 }
668 }
669 return false;
670}
671
439e1497 672bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
0b807a41 673{
ca4cf5cf 674 LOCK(cs_wallet); // nWalletVersion
0b807a41
PW
675 if (nWalletVersion >= nVersion)
676 return true;
677
439e1497
PW
678 // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
679 if (fExplicit && nVersion > nWalletMaxVersion)
680 nVersion = FEATURE_LATEST;
681
0b807a41
PW
682 nWalletVersion = nVersion;
683
439e1497
PW
684 if (nVersion > nWalletMaxVersion)
685 nWalletMaxVersion = nVersion;
686
0b807a41
PW
687 if (fFileBacked)
688 {
689 CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
0b807a41
PW
690 if (nWalletVersion > 40000)
691 pwalletdb->WriteMinVersion(nWalletVersion);
692 if (!pwalletdbIn)
693 delete pwalletdb;
694 }
695
696 return true;
697}
698
439e1497
PW
699bool CWallet::SetMaxVersion(int nVersion)
700{
ca4cf5cf 701 LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
439e1497
PW
702 // cannot downgrade below current version
703 if (nWalletVersion > nVersion)
704 return false;
705
706 nWalletMaxVersion = nVersion;
707
708 return true;
709}
710
3015e0bc 711set<uint256> CWallet::GetConflicts(const uint256& txid) const
731b89b8
GA
712{
713 set<uint256> result;
714 AssertLockHeld(cs_wallet);
715
716 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
717 if (it == mapWallet.end())
718 return result;
719 const CWalletTx& wtx = it->second;
720
93a18a36 721 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
731b89b8
GA
722
723 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
724 {
93a18a36
GA
725 if (mapTxSpends.count(txin.prevout) <= 1)
726 continue; // No conflict if zero or one spends
727 range = mapTxSpends.equal_range(txin.prevout);
728 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
3015e0bc 729 result.insert(it->second);
731b89b8 730 }
0f106047
JG
731
732 std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
733
734 for (const JSDescription& jsdesc : wtx.vjoinsplit) {
735 for (const uint256& nullifier : jsdesc.nullifiers) {
3438e26c 736 if (mapTxSproutNullifiers.count(nullifier) <= 1) {
0f106047
JG
737 continue; // No conflict if zero or one spends
738 }
3438e26c 739 range_n = mapTxSproutNullifiers.equal_range(nullifier);
0f106047
JG
740 for (TxNullifiers::const_iterator it = range_n.first; it != range_n.second; ++it) {
741 result.insert(it->second);
742 }
743 }
744 }
3afc6ce2
S
745
746 std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_o;
747
748 for (const SpendDescription &spend : wtx.vShieldedSpend) {
749 uint256 nullifier = spend.nullifier;
750 if (mapTxSaplingNullifiers.count(nullifier) <= 1) {
751 continue; // No conflict if zero or one spends
752 }
753 range_o = mapTxSaplingNullifiers.equal_range(nullifier);
754 for (TxNullifiers::const_iterator it = range_o.first; it != range_o.second; ++it) {
755 result.insert(it->second);
756 }
0f106047 757 }
731b89b8
GA
758 return result;
759}
760
2bb1c877
JS
761void CWallet::Flush(bool shutdown)
762{
763 bitdb.Flush(shutdown);
764}
765
341e2385 766bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
2bb1c877
JS
767{
768 if (!bitdb.Open(GetDataDir()))
769 {
770 // try moving the database env out of the way
771 boost::filesystem::path pathDatabase = GetDataDir() / "database";
772 boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%d.bak", GetTime());
773 try {
774 boost::filesystem::rename(pathDatabase, pathDatabaseBak);
775 LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string());
776 } catch (const boost::filesystem::filesystem_error&) {
777 // failure is ok (well, not really, but it's not worse than what we started with)
778 }
efb7662d 779
2bb1c877
JS
780 // try again
781 if (!bitdb.Open(GetDataDir())) {
782 // if it still fails, it probably means we can't even create the database env
783 string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
784 errorString += msg;
785 return true;
786 }
787 }
efb7662d 788
2bb1c877
JS
789 if (GetBoolArg("-salvagewallet", false))
790 {
791 // Recover readable keypairs:
792 if (!CWalletDB::Recover(bitdb, walletFile, true))
793 return false;
794 }
efb7662d 795
2bb1c877
JS
796 if (boost::filesystem::exists(GetDataDir() / walletFile))
797 {
798 CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
799 if (r == CDBEnv::RECOVER_OK)
800 {
801 warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
802 " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
803 " your balance or transactions are incorrect you should"
804 " restore from a backup."), GetDataDir());
805 }
806 if (r == CDBEnv::RECOVER_FAIL)
807 errorString += _("wallet.dat corrupt, salvage failed");
808 }
efb7662d 809
2bb1c877
JS
810 return true;
811}
812
0f106047
JG
813template <class T>
814void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator> range)
731b89b8
GA
815{
816 // We want all the wallet transactions in range to have the same metadata as
817 // the oldest (smallest nOrderPos).
818 // So: find smallest nOrderPos:
819
820 int nMinOrderPos = std::numeric_limits<int>::max();
821 const CWalletTx* copyFrom = NULL;
0f106047 822 for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
731b89b8
GA
823 {
824 const uint256& hash = it->second;
825 int n = mapWallet[hash].nOrderPos;
826 if (n < nMinOrderPos)
827 {
828 nMinOrderPos = n;
829 copyFrom = &mapWallet[hash];
830 }
831 }
832 // Now copy data from copyFrom to rest:
0f106047 833 for (typename TxSpendMap<T>::iterator it = range.first; it != range.second; ++it)
731b89b8
GA
834 {
835 const uint256& hash = it->second;
836 CWalletTx* copyTo = &mapWallet[hash];
837 if (copyFrom == copyTo) continue;
838 copyTo->mapValue = copyFrom->mapValue;
303f80fb 839 // mapSproutNoteData and mapSaplingNoteData not copied on purpose
c3a7307a 840 // (it is always set correctly for each CWalletTx)
731b89b8
GA
841 copyTo->vOrderForm = copyFrom->vOrderForm;
842 // fTimeReceivedIsTxTime not copied on purpose
843 // nTimeReceived not copied on purpose
844 copyTo->nTimeSmart = copyFrom->nTimeSmart;
845 copyTo->fFromMe = copyFrom->fFromMe;
846 copyTo->strFromAccount = copyFrom->strFromAccount;
731b89b8
GA
847 // nOrderPos not copied on purpose
848 // cached members not copied on purpose
849 }
850}
851
5b40d886
MF
852/**
853 * Outpoint is spent if any non-conflicted transaction
854 * spends it:
855 */
93a18a36 856bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
731b89b8 857{
93a18a36
GA
858 const COutPoint outpoint(hash, n);
859 pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
860 range = mapTxSpends.equal_range(outpoint);
731b89b8 861
93a18a36 862 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
731b89b8 863 {
93a18a36
GA
864 const uint256& wtxid = it->second;
865 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
866 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
867 return true; // Spent
731b89b8 868 }
93a18a36
GA
869 return false;
870}
871
0f106047
JG
872/**
873 * Note is spent if any non-conflicted transaction
874 * spends it:
875 */
3b6dd486 876bool CWallet::IsSproutSpent(const uint256& nullifier) const {
0f106047 877 pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
3438e26c 878 range = mapTxSproutNullifiers.equal_range(nullifier);
0f106047
JG
879
880 for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
881 const uint256& wtxid = it->second;
882 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
883 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
884 return true; // Spent
885 }
886 }
887 return false;
888}
889
3b6dd486
S
890bool CWallet::IsSaplingSpent(const uint256& nullifier) const {
891 pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
edfc6a78
S
892 range = mapTxSaplingNullifiers.equal_range(nullifier);
893
894 for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
895 const uint256& wtxid = it->second;
0f106047
JG
896 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
897 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
898 return true; // Spent
899 }
900 }
901 return false;
902}
903
d5e490d9 904void CWallet::AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid)
93a18a36
GA
905{
906 mapTxSpends.insert(make_pair(outpoint, wtxid));
907
908 pair<TxSpends::iterator, TxSpends::iterator> range;
909 range = mapTxSpends.equal_range(outpoint);
0f106047 910 SyncMetaData<COutPoint>(range);
93a18a36
GA
911}
912
d5e490d9 913void CWallet::AddToSproutSpends(const uint256& nullifier, const uint256& wtxid)
0f106047 914{
3438e26c 915 mapTxSproutNullifiers.insert(make_pair(nullifier, wtxid));
0f106047
JG
916
917 pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
3438e26c 918 range = mapTxSproutNullifiers.equal_range(nullifier);
0f106047
JG
919 SyncMetaData<uint256>(range);
920}
93a18a36 921
c343e2db
S
922void CWallet::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid)
923{
924 mapTxSaplingNullifiers.insert(make_pair(nullifier, wtxid));
925
926 pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
927 range = mapTxSaplingNullifiers.equal_range(nullifier);
0f106047
JG
928 SyncMetaData<uint256>(range);
929}
93a18a36
GA
930
931void CWallet::AddToSpends(const uint256& wtxid)
932{
933 assert(mapWallet.count(wtxid));
934 CWalletTx& thisTx = mapWallet[wtxid];
935 if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
936 return;
937
0f106047 938 for (const CTxIn& txin : thisTx.vin) {
d5e490d9 939 AddToTransparentSpends(txin.prevout, wtxid);
0f106047
JG
940 }
941 for (const JSDescription& jsdesc : thisTx.vjoinsplit) {
942 for (const uint256& nullifier : jsdesc.nullifiers) {
d5e490d9 943 AddToSproutSpends(nullifier, wtxid);
0f106047
JG
944 }
945 }
52332fb4
S
946 for (const SpendDescription &spend : thisTx.vShieldedSpend) {
947 AddToSaplingSpends(spend.nullifier, wtxid);
948 }
731b89b8
GA
949}
950
76b22658
JG
951void CWallet::ClearNoteWitnessCache()
952{
953 LOCK(cs_wallet);
954 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
005f3ad1 955 for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) {
40600f50 956 item.second.witnesses.clear();
a4ef3aa9 957 item.second.witnessHeight = -1;
76b22658 958 }
403b9b4e 959 for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
40600f50 960 item.second.witnesses.clear();
a4ef3aa9 961 item.second.witnessHeight = -1;
76b22658
JG
962 }
963 }
a4ef3aa9 964 nWitnessCacheSize = 0;
a7f86bc7 965 //fprintf(stderr,"Clear witness cache\n");
76b22658
JG
966}
967
b5380248
EOW
968template<typename NoteDataMap>
969void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
970{
971 for (auto& item : noteDataMap) {
972 auto* nd = &(item.second);
973 // Only increment witnesses that are behind the current height
974 if (nd->witnessHeight < indexHeight) {
975 // Check the validity of the cache
976 // The only time a note witnessed above the current height
977 // would be invalid here is during a reindex when blocks
978 // have been decremented, and we are incrementing the blocks
979 // immediately after.
980 assert(nWitnessCacheSize >= nd->witnesses.size());
981 // Witnesses being incremented should always be either -1
982 // (never incremented or decremented) or one below indexHeight
983 assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight - 1));
984 // Copy the witness for the previous block if we have one
985 if (nd->witnesses.size() > 0) {
986 nd->witnesses.push_front(nd->witnesses.front());
987 }
988 if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
989 nd->witnesses.pop_back();
be74c80d
JG
990 }
991 }
b5380248
EOW
992 }
993}
994
f6d0d5ec
EOW
995template<typename NoteDataMap>
996void AppendNoteCommitment(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment)
997{
998 for (auto& item : noteDataMap) {
999 auto* nd = &(item.second);
1000 if (nd->witnessHeight < indexHeight && nd->witnesses.size() > 0) {
1001 // Check the validity of the cache
1002 // See comment in CopyPreviousWitnesses about validity.
1003 assert(nWitnessCacheSize >= nd->witnesses.size());
1004 nd->witnesses.front().append(note_commitment);
8a7d37be 1005 }
f6d0d5ec
EOW
1006 }
1007}
be74c80d 1008
f6d0d5ec
EOW
1009template<typename OutPoint, typename NoteData, typename Witness>
1010void WitnessNoteIfMine(std::map<OutPoint, NoteData>& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const OutPoint& key, const Witness& witness)
1011{
1012 if (noteDataMap.count(key) && noteDataMap[key].witnessHeight < indexHeight) {
1013 auto* nd = &(noteDataMap[key]);
1014 if (nd->witnesses.size() > 0) {
1015 // We think this can happen because we write out the
1016 // witness cache state after every block increment or
1017 // decrement, but the block index itself is written in
1018 // batches. So if the node crashes in between these two
1019 // operations, it is possible for IncrementNoteWitnesses
1020 // to be called again on previously-cached blocks. This
1021 // doesn't affect existing cached notes because of the
1022 // NoteData::witnessHeight checks. See #1378 for details.
1023 LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n",
1024 key.ToString(), nd->witnesses.size(),
1025 nd->witnessHeight,
1026 nd->witnesses.front().root().GetHex(),
1027 indexHeight,
1028 witness.root().GetHex());
1029 nd->witnesses.clear();
be74c80d 1030 }
f6d0d5ec
EOW
1031 nd->witnesses.push_front(witness);
1032 // Set height to one less than pindex so it gets incremented
1033 nd->witnessHeight = indexHeight - 1;
1034 // Check the validity of the cache
1035 assert(nWitnessCacheSize >= nd->witnesses.size());
1036 }
1037}
be74c80d 1038
be74c80d 1039
4a0bc604
EOW
1040template<typename NoteDataMap>
1041void UpdateWitnessHeights(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
1042{
1043 for (auto& item : noteDataMap) {
1044 auto* nd = &(item.second);
1045 if (nd->witnessHeight < indexHeight) {
1046 nd->witnessHeight = indexHeight;
1047 // Check the validity of the cache
1048 // See comment in CopyPreviousWitnesses about validity.
1049 assert(nWitnessCacheSize >= nd->witnesses.size());
1050 }
1051 }
1052}
be74c80d 1053
be74c80d
JG
1054void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
1055 const CBlock* pblockIn,
4fc309f0
EOW
1056 SproutMerkleTree& sproutTree,
1057 SaplingMerkleTree& saplingTree)
be74c80d 1058{
49695a97
EOW
1059 LOCK(cs_wallet);
1060 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
4b729ec5 1061 ::CopyPreviousWitnesses(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize);
1062 ::CopyPreviousWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize);
49695a97 1063 }
b5380248 1064
49695a97
EOW
1065 if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
1066 nWitnessCacheSize += 1;
1067 }
be74c80d 1068
49695a97
EOW
1069 const CBlock* pblock {pblockIn};
1070 CBlock block;
1071 if (!pblock) {
9feb4b9e 1072 ReadBlockFromDisk(block, pindex, false);
49695a97
EOW
1073 pblock = &block;
1074 }
be74c80d 1075
49695a97
EOW
1076 for (const CTransaction& tx : pblock->vtx) {
1077 auto hash = tx.GetHash();
1078 bool txIsOurs = mapWallet.count(hash);
45de2eda 1079 // Sprout
49695a97
EOW
1080 for (size_t i = 0; i < tx.vjoinsplit.size(); i++) {
1081 const JSDescription& jsdesc = tx.vjoinsplit[i];
1082 for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) {
1083 const uint256& note_commitment = jsdesc.commitments[j];
f86ee1c2 1084 sproutTree.append(note_commitment);
be74c80d 1085
49695a97
EOW
1086 // Increment existing witnesses
1087 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
4b729ec5 1088 ::AppendNoteCommitment(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
be74c80d 1089 }
b6961fc1 1090
49695a97
EOW
1091 // If this is our note, witness it
1092 if (txIsOurs) {
1093 JSOutPoint jsoutpt {hash, i, j};
4b729ec5 1094 ::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize, jsoutpt, sproutTree.witness());
be74c80d
JG
1095 }
1096 }
1097 }
45de2eda
EOW
1098 // Sapling
1099 for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) {
1100 const uint256& note_commitment = tx.vShieldedOutput[i].cm;
1101 saplingTree.append(note_commitment);
1102
1103 // Increment existing witnesses
1104 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
4b729ec5 1105 ::AppendNoteCommitment(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, note_commitment);
45de2eda 1106 }
b6961fc1 1107
45de2eda
EOW
1108 // If this is our note, witness it
1109 if (txIsOurs) {
1110 SaplingOutPoint outPoint {hash, i};
4b729ec5 1111 ::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize, outPoint, saplingTree.witness());
83d7b5b6
JG
1112 }
1113 }
49695a97 1114 }
b6961fc1 1115
49695a97
EOW
1116 // Update witness heights
1117 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
4b729ec5 1118 ::UpdateWitnessHeights(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize);
1119 ::UpdateWitnessHeights(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize);
be74c80d 1120 }
49695a97
EOW
1121
1122 // For performance reasons, we write out the witness cache in
1123 // CWallet::SetBestChain() (which also ensures that overall consistency
1124 // of the wallet.dat is maintained).
be74c80d
JG
1125}
1126
9d804cc6 1127template<typename NoteDataMap>
47ab0926 1128bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
be74c80d 1129{
8ba45413 1130 extern int32_t KOMODO_REWIND;
9feb4b9e 1131
9d804cc6
EOW
1132 for (auto& item : noteDataMap) {
1133 auto* nd = &(item.second);
1134 // Only decrement witnesses that are not above the current height
1135 if (nd->witnessHeight <= indexHeight) {
49695a97 1136 // Check the validity of the cache
9d804cc6
EOW
1137 // See comment below (this would be invalid if there were a
1138 // prior decrement).
1139 assert(nWitnessCacheSize >= nd->witnesses.size());
1140 // Witnesses being decremented should always be either -1
1141 // (never incremented or decremented) or equal to the height
1142 // of the block being removed (indexHeight)
47ab0926 1143 if (!((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight)))
1144 {
1145 printf("at height %d\n", indexHeight);
1146 return false;
1147 }
9d804cc6
EOW
1148 if (nd->witnesses.size() > 0) {
1149 nd->witnesses.pop_front();
be74c80d 1150 }
9d804cc6
EOW
1151 // indexHeight is the height of the block being removed, so
1152 // the new witness cache height is one below it.
1153 nd->witnessHeight = indexHeight - 1;
be74c80d 1154 }
9d804cc6
EOW
1155 // Check the validity of the cache
1156 // Technically if there are notes witnessed above the current
1157 // height, their cache will now be invalid (relative to the new
1158 // value of nWitnessCacheSize). However, this would only occur
1159 // during a reindex, and by the time the reindex reaches the tip
1160 // of the chain again, the existing witness caches will be valid
1161 // again.
1162 // We don't set nWitnessCacheSize to zero at the start of the
1163 // reindex because the on-disk blocks had already resulted in a
1164 // chain that didn't trigger the assertion below.
1165 if (nd->witnessHeight < indexHeight) {
1166 // Subtract 1 to compare to what nWitnessCacheSize will be after
1167 // decrementing.
1168 assert((nWitnessCacheSize - 1) >= nd->witnesses.size());
4c73b58b 1169 }
be74c80d 1170 }
9feb4b9e 1171 assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0);
47ab0926 1172 return true;
9d804cc6
EOW
1173}
1174
1175void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
1176{
1177 LOCK(cs_wallet);
1178 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
47ab0926 1179 if (!::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->GetHeight(), nWitnessCacheSize))
1180 needsRescan = true;
1181 if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->GetHeight(), nWitnessCacheSize))
1182 needsRescan = true;
9d804cc6 1183 }
3c868d2b 1184 nWitnessCacheSize -= 1;
49695a97
EOW
1185 // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302)
1186 assert(nWitnessCacheSize > 0);
1187
1188 // For performance reasons, we write out the witness cache in
1189 // CWallet::SetBestChain() (which also ensures that overall consistency
1190 // of the wallet.dat is maintained).
be74c80d
JG
1191}
1192
94f778bd 1193bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
4e87d341 1194{
6cc4a62c
GA
1195 if (IsCrypted())
1196 return false;
4e87d341 1197
6cc4a62c 1198 CKeyingMaterial vMasterKey;
4e87d341 1199
6cc4a62c 1200 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
65e3a1e7 1201 GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
4e87d341 1202
6cc4a62c 1203 CMasterKey kMasterKey;
001a53d7 1204
6cc4a62c 1205 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
65e3a1e7 1206 GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
4e87d341 1207
6cc4a62c 1208 CCrypter crypter;
51ed9ec9 1209 int64_t nStartTime = GetTimeMillis();
6cc4a62c
GA
1210 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
1211 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
ddebdd9a 1212
6cc4a62c
GA
1213 nStartTime = GetTimeMillis();
1214 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
1215 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
ddebdd9a 1216
6cc4a62c
GA
1217 if (kMasterKey.nDeriveIterations < 25000)
1218 kMasterKey.nDeriveIterations = 25000;
ddebdd9a 1219
881a85a2 1220 LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
ddebdd9a 1221
6cc4a62c
GA
1222 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
1223 return false;
1224 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
1225 return false;
4e87d341 1226
6cc4a62c 1227 {
f8dcd5ca 1228 LOCK(cs_wallet);
4e87d341
MC
1229 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
1230 if (fFileBacked)
1231 {
870da77d 1232 assert(!pwalletdbEncryption);
96f34cd5 1233 pwalletdbEncryption = new CWalletDB(strWalletFile);
870da77d
PK
1234 if (!pwalletdbEncryption->TxnBegin()) {
1235 delete pwalletdbEncryption;
1236 pwalletdbEncryption = NULL;
0fb78eae 1237 return false;
870da77d 1238 }
96f34cd5 1239 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
4e87d341
MC
1240 }
1241
1242 if (!EncryptKeys(vMasterKey))
96f34cd5 1243 {
870da77d 1244 if (fFileBacked) {
96f34cd5 1245 pwalletdbEncryption->TxnAbort();
870da77d
PK
1246 delete pwalletdbEncryption;
1247 }
1248 // We now probably have half of our keys encrypted in memory, and half not...
7e6d23b1 1249 // die and let the user reload the unencrypted wallet.
d0c4197e 1250 assert(false);
96f34cd5
MC
1251 }
1252
0b807a41 1253 // Encryption was introduced in version 0.4.0
439e1497 1254 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
0b807a41 1255
96f34cd5
MC
1256 if (fFileBacked)
1257 {
870da77d
PK
1258 if (!pwalletdbEncryption->TxnCommit()) {
1259 delete pwalletdbEncryption;
5b40d886 1260 // We now have keys encrypted in memory, but not on disk...
7e6d23b1 1261 // die to avoid confusion and let the user reload the unencrypted wallet.
d0c4197e 1262 assert(false);
870da77d 1263 }
96f34cd5 1264
fcfd7ff8 1265 delete pwalletdbEncryption;
96f34cd5
MC
1266 pwalletdbEncryption = NULL;
1267 }
4e87d341 1268
37971fcc
GA
1269 Lock();
1270 Unlock(strWalletPassphrase);
1271 NewKeyPool();
4e87d341 1272 Lock();
6cc4a62c 1273
d764d916
GA
1274 // Need to completely rewrite the wallet file; if we don't, bdb might keep
1275 // bits of the unencrypted private key in slack space in the database file.
b2d3b2d6 1276 CDB::Rewrite(strWalletFile);
fe4a6550 1277
d764d916 1278 }
ab1b288f 1279 NotifyStatusChanged(this);
9e9869d0 1280
4e87d341 1281 return true;
e8ef3da7
WL
1282}
1283
51ed9ec9 1284int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
da7b8c12 1285{
95691680 1286 AssertLockHeld(cs_wallet); // nOrderPosNext
51ed9ec9 1287 int64_t nRet = nOrderPosNext++;
4291e8fe
PW
1288 if (pwalletdb) {
1289 pwalletdb->WriteOrderPosNext(nOrderPosNext);
1290 } else {
1291 CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
1292 }
da7b8c12
LD
1293 return nRet;
1294}
1295
ddb709e9 1296CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
c3f95ef1 1297{
95691680 1298 AssertLockHeld(cs_wallet); // mapWallet
c3f95ef1
LD
1299 CWalletDB walletdb(strWalletFile);
1300
1301 // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
1302 TxItems txOrdered;
1303
1304 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1305 // would make this much faster for applications that do this a lot.
1306 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1307 {
1308 CWalletTx* wtx = &((*it).second);
1309 txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
1310 }
ddb709e9 1311 acentries.clear();
c3f95ef1
LD
1312 walletdb.ListAccountCreditDebit(strAccount, acentries);
1313 BOOST_FOREACH(CAccountingEntry& entry, acentries)
1314 {
1315 txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
1316 }
1317
1318 return txOrdered;
1319}
1320
1f722359
MT
1321// 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
1322// UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving
1323// each attempt consists of taking a VerusHash of the following values:
1324// ASSETCHAINS_MAGIC, nHeight, txid, voutNum
17d0160a 1325bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const
1f722359 1326{
c5325a32 1327 arith_uint256 target;
1f722359
MT
1328 arith_uint256 curHash;
1329 vector<COutput> vecOutputs;
1330 COutput *pwinner = NULL;
1331 CBlockIndex *pastBlockIndex;
1fae37f6
MT
1332 txnouttype whichType;
1333 std:vector<std::vector<unsigned char>> vSolutions;
1f722359 1334
12217420 1335 pBlock->nNonce.SetPOSTarget(bnTarget, pBlock->nVersion);
c5325a32
MT
1336 target.SetCompact(bnTarget);
1337
1f722359
MT
1338 pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
1339
c5325a32 1340 if (pastBlockIndex = komodo_chainactive(nHeight - 100))
1f722359 1341 {
b2a98c42 1342 uint256 pastHash = pastBlockIndex->GetVerusEntropyHash();
17d0160a 1343 CPOSNonce curNonce;
b2a98c42 1344 uint32_t srcIndex;
1f722359
MT
1345
1346 BOOST_FOREACH(COutput &txout, vecOutputs)
1347 {
c5325a32 1348 if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE))
1f722359 1349 {
b2a98c42 1350 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
85c51d62 1351
f8f61a6d 1352 printf("Serialized size of transaction %lu\n", GetSerializeSize(s, *(CTransaction *)txout.tx));
85c51d62 1353
c68ca1a2 1354 if ((!pwinner || UintToArith256(curNonce) > UintToArith256(pBlock->nNonce)) &&
b276e368 1355 (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH)) &&
b2a98c42
MT
1356 !cheatList.IsUTXOInList(COutPoint(txout.tx->GetHash(), txout.i), nHeight <= 100 ? 1 : nHeight-100) &&
1357 GetSerializeSize(s, *(CTransaction *)txout.tx) <= MAX_TX_SIZE_FOR_STAKING)
c68ca1a2 1358 {
85ca7bb9 1359 //printf("Found PoS block\nnNonce: %s\n", pBlock->nNonce.GetHex().c_str());
1f722359 1360 pwinner = &txout;
17d0160a 1361 curNonce = pBlock->nNonce;
b2a98c42 1362 srcIndex = (nHeight - txout.nDepth) - 1;
c68ca1a2 1363 }
1f722359
MT
1364 }
1365 }
1366 if (pwinner)
1367 {
1368 stakeSource = *(pwinner->tx);
1369 voutNum = pwinner->i;
17d0160a 1370 pBlock->nNonce = curNonce;
ec1c84a0 1371
b2a98c42 1372 if (CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight) == CActivationHeight::SOLUTION_VERUSV3)
ec1c84a0
MT
1373 {
1374 CDataStream txStream = CDataStream(SER_NETWORK, PROTOCOL_VERSION);
ec1c84a0 1375
b2a98c42
MT
1376 // store:
1377 // 1. PBaaS header for this block
1378 // 2. source transaction
1379 // 3. block index of base MMR being used
1380 // 4. source tx block index for proof
1381 // 5. full merkle proof of source tx up to prior MMR root
1382 // 6. block hash of block of entropyhash
1383 // 7. proof of block hash (not full header) in the MMR for the block height of the entropy hash block
1384 // all that data includes enough information to verify
1385 // prior MMR, blockhash, transaction, entropy hash, and block indexes match
1386 // also checks root match & block power
25eff798
MT
1387 auto view = chainActive.GetMMV();
1388 pBlock->AddUpdatePBaaSHeader(view.GetRoot());
ec1c84a0 1389
b2a98c42 1390 txStream << *(CTransaction *)pwinner->tx;
ec1c84a0 1391
b2a98c42
MT
1392 // start with the tx proof
1393 CMerkleBranch branch(pwinner->tx->nIndex, pwinner->tx->vMerkleBranch);
ec1c84a0 1394
b2a98c42
MT
1395 // add the Merkle proof bridge to the MMR
1396 chainActive[srcIndex]->AddMerkleProofBridge(branch);
1397
1398 // use the block that we got entropy hash from as the validating block
1399 // which immediately provides all but unspent proof for PoS block
25eff798 1400 view.resize(pastBlockIndex->GetHeight());
b2a98c42
MT
1401
1402 view.GetProof(branch, srcIndex);
1403
1404 // store block height of MMR root, block index of entry, and full blockchain proof of transaction with that root
1405 txStream << pastBlockIndex->GetHeight();
1406 txStream << srcIndex;
1407 txStream << branch;
1408
1409 // now we get a fresh branch for the block proof
1410 branch = CMerkleBranch();
1411
1412 // prove the block 100 blocks ago with its coincident MMR
1413 // it must hash to the same value with a different path, providing both a consistency check and
1414 // an asserted MMR root for the n - 100 block if matched
1415 pastBlockIndex->AddBlockProofBridge(branch);
1416 view.GetProof(branch, pastBlockIndex->GetHeight());
1417
1418 // block proof of the same block using the MMR of that block height, so we don't need to add additional data
25eff798 1419 // beyond the block hash.
b2a98c42
MT
1420 txStream << pastBlockIndex->GetBlockHash();
1421 txStream << branch;
1422
1423 std::vector<unsigned char> stx(txStream.begin(), txStream.end());
1424
f8f61a6d 1425 // printf("\nFound Stake transaction... all proof serialized size == %lu\n", stx.size());
b2a98c42 1426
b2a98c42
MT
1427 CVerusSolutionVector(pBlock->nSolution).ResizeExtraData(stx.size());
1428
1429 pBlock->SetExtraData(stx.data(), stx.size());
ec1c84a0 1430 }
1f722359
MT
1431 return true;
1432 }
1433 }
1434 return false;
1435}
1436
06f41160 1437int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey pk) const
1f722359 1438{
1f722359
MT
1439 CTransaction stakeSource;
1440 int32_t voutNum, siglen = 0;
1441 int64_t nValue;
1fae37f6
MT
1442 txnouttype whichType;
1443 std::vector<std::vector<unsigned char>> vSolutions;
1f722359 1444
3bfa5e22 1445 CBlockIndex *tipindex = chainActive.LastTip();
1446 uint32_t stakeHeight = tipindex->GetHeight() + 1;
1447 bool extendedStake = stakeHeight >= Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight;
8a727a26 1448
06f41160 1449 if (!extendedStake)
1450 pk = CPubKey();
1451
1f722359 1452 bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus());
1f722359 1453
ec1c84a0 1454 if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, stakeHeight, bnTarget) ||
1fae37f6 1455 !Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions))
1f722359 1456 {
c5325a32 1457 LogPrintf("Searched for eligible staking transactions, no winners found\n");
1f722359
MT
1458 return 0;
1459 }
1460
1f722359
MT
1461 bool signSuccess;
1462 SignatureData sigdata;
86e31e3d 1463 uint64_t txfee;
86e31e3d 1464 auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
1f722359
MT
1465
1466 const CKeyStore& keystore = *pwalletMain;
1467 txNew.vin.resize(1);
1468 txNew.vout.resize(1);
f1f6dfbb 1469 txfee = extendedStake ? DEFAULT_STAKE_TXFEE : 0;
1f722359
MT
1470 txNew.vin[0].prevout.hash = stakeSource.GetHash();
1471 txNew.vin[0].prevout.n = voutNum;
1472
1fae37f6
MT
1473 if (whichType == TX_PUBKEY)
1474 {
1475 txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG;
06f41160 1476 if (!pk.IsValid())
1477 pk = CPubKey(vSolutions[0]);
1fae37f6
MT
1478 }
1479 else if (whichType == TX_PUBKEYHASH)
1480 {
1481 txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
06f41160 1482 if (extendedStake && !pk.IsValid())
8a727a26 1483 {
1484 // we need a pubkey, so try to get one from the key ID, if not there, fail
1485 if (!keystore.GetPubKey(CKeyID(uint160(vSolutions[0])), pk))
1486 return 0;
1487 }
1fae37f6
MT
1488 }
1489 else
1490 return 0;
1f722359 1491
8a727a26 1492 // if we are staking with the extended format, add the opreturn data required
905fe35e 1493 if (extendedStake)
8a727a26 1494 {
7a993143 1495 // set expiry to time out after 100 blocks, so we can remove the transaction if it orphans
1496 txNew.nExpiryHeight = stakeHeight + 100;
1497
8a727a26 1498 uint256 srcBlock = uint256();
1499 CBlockIndex *pSrcIndex;
1500
1501 txNew.vout.push_back(CTxOut());
1502 CTxOut &txOut1 = txNew.vout[1];
1503 txOut1.nValue = 0;
1504 if (!GetTransaction(stakeSource.GetHash(), stakeSource, srcBlock))
1505 return 0;
1506
d565e7b7 1507 BlockMap::const_iterator it = mapBlockIndex.find(srcBlock);
1508 if (it == mapBlockIndex.end() || (pSrcIndex = it->second) == 0)
8a727a26 1509 return 0;
1510
ec8a120b 1511 // !! DISABLE THIS FOR RELEASE: THIS MAKES A CHEAT TRANSACTION FOR EVERY STAKE FOR TESTING
9befb850 1512 //CMutableTransaction cheat;
1513 //cheat = CMutableTransaction(txNew);
1514 //printf("TESTING ONLY: THIS SHOULD NOT BE ENABLED FOR RELEASE - MAKING CHEAT TRANSACTION FOR TESTING\n");
1515 //cheat.vout[1].scriptPubKey << OP_RETURN
1516 // << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, pSrcIndex->GetBlockHash(), pk).AsVector();
ec8a120b 1517 // !! DOWN TO HERE
43260416 1518
8a727a26 1519 txOut1.scriptPubKey << OP_RETURN
3bfa5e22 1520 << CStakeParams(pSrcIndex->GetHeight(), tipindex->GetHeight() + 1, tipindex->GetBlockHash(), pk).AsVector();
8a727a26 1521
41e9e058 1522 // !! DISABLE THIS FOR RELEASE: REMOVE THIS TOO
9befb850 1523 //nValue = cheat.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
1524 //cheat.nLockTime = 0;
1525 //CTransaction cheatConst(cheat);
1526 //SignatureData cheatSig;
1527 //if (!ProduceSignature(TransactionSignatureCreator(&keystore, &cheatConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, cheatSig, consensusBranchId))
1528 // fprintf(stderr,"failed to create cheat test signature\n");
1529 //else
1530 //{
1531 // uint8_t *ptr;
1532 // UpdateTransaction(cheat,0,cheatSig);
1533 // cheatList.Add(CTxHolder(CTransaction(cheat), tipindex->GetHeight() + 1));
1534 //}
41e9e058 1535 // !! DOWN TO HERE
1536 }
43260416 1537
31bbe234 1538 nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee;
3bfa5e22 1539
1f722359
MT
1540 txNew.nLockTime = 0;
1541 CTransaction txNewConst(txNew);
1542 signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, sigdata, consensusBranchId);
1543 if (!signSuccess)
1544 fprintf(stderr,"failed to create signature\n");
1545 else
1546 {
1547 uint8_t *ptr;
1548 UpdateTransaction(txNew,0,sigdata);
9feb4b9e 1549 ptr = (uint8_t *)&sigdata.scriptSig[0];
1f722359
MT
1550 siglen = sigdata.scriptSig.size();
1551 for (int i=0; i<siglen; i++)
1552 utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
1553 }
1554 return(siglen);
1555}
1556
95d888a6
PW
1557void CWallet::MarkDirty()
1558{
95d888a6 1559 {
f8dcd5ca 1560 LOCK(cs_wallet);
95d888a6
PW
1561 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
1562 item.second.MarkDirty();
1563 }
1564}
1565
1a62587e 1566/**
9a2b8ae5
JG
1567 * Ensure that every note in the wallet (for which we possess a spending key)
1568 * has a cached nullifier.
1a62587e
JG
1569 */
1570bool CWallet::UpdateNullifierNoteMap()
1571{
1572 {
1573 LOCK(cs_wallet);
1574
1575 if (IsLocked())
1576 return false;
1577
1578 ZCNoteDecryption dec;
1579 for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
005f3ad1 1580 for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) {
1a62587e 1581 if (!item.second.nullifier) {
9a2b8ae5
JG
1582 if (GetNoteDecryptor(item.second.address, dec)) {
1583 auto i = item.first.js;
1584 auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
1585 *pzcashParams, wtxItem.second.joinSplitPubKey);
618206c7 1586 item.second.nullifier = GetSproutNoteNullifier(
9a2b8ae5
JG
1587 wtxItem.second.vjoinsplit[i],
1588 item.second.address,
1589 dec,
1590 hSig,
1591 item.first.n);
1592 }
1a62587e
JG
1593 }
1594 }
ad1e90dd
S
1595
1596 // TODO: Sapling. This method is only called from RPC walletpassphrase, which is currently unsupported
1597 // as RPC encryptwallet is hidden behind two flags: -developerencryptwallet -experimentalfeatures
1598
6e263a5f 1599 UpdateNullifierNoteMapWithTx(wtxItem.second);
1a62587e
JG
1600 }
1601 }
1602 return true;
1603}
1604
6e263a5f 1605/**
ad1e90dd
S
1606 * Update mapSproutNullifiersToNotes and mapSaplingNullifiersToNotes
1607 * with the cached nullifiers in this tx.
6e263a5f
JG
1608 */
1609void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
8db7e25c
JG
1610{
1611 {
1612 LOCK(cs_wallet);
005f3ad1 1613 for (const mapSproutNoteData_t::value_type& item : wtx.mapSproutNoteData) {
1a62587e 1614 if (item.second.nullifier) {
f41bf503 1615 mapSproutNullifiersToNotes[*item.second.nullifier] = item.first;
1a62587e 1616 }
8db7e25c 1617 }
ad1e90dd
S
1618
1619 for (const mapSaplingNoteData_t::value_type& item : wtx.mapSaplingNoteData) {
1a62587e 1620 if (item.second.nullifier) {
ad1e90dd 1621 mapSaplingNullifiersToNotes[*item.second.nullifier] = item.first;
1a62587e 1622 }
8db7e25c
JG
1623 }
1624 }
1625}
1626
ad1e90dd
S
1627/**
1628 * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
1629 */
1630void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
1631 LOCK(cs_wallet);
1632
1633 for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
1634 SaplingOutPoint op = item.first;
1635 SaplingNoteData nd = item.second;
1636
c343e2db 1637 if (nd.witnesses.empty()) {
ad1e90dd
S
1638 // If there are no witnesses, erase the nullifier and associated mapping.
1639 if (item.second.nullifier) {
1640 mapSaplingNullifiersToNotes.erase(item.second.nullifier.get());
1641 }
1642 item.second.nullifier = boost::none;
1643 }
c343e2db 1644 else {
ad1e90dd
S
1645 uint64_t position = nd.witnesses.front().position();
1646 SaplingFullViewingKey fvk = mapSaplingFullViewingKeys.at(nd.ivk);
1647 OutputDescription output = wtx.vShieldedOutput[op.n];
1648 auto optPlaintext = SaplingNotePlaintext::decrypt(output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
1649 if (!optPlaintext) {
1650 // An item in mapSaplingNoteData must have already been successfully decrypted,
1651 // otherwise the item would not exist in the first place.
1652 assert(false);
1653 }
1654 auto optNote = optPlaintext.get().note(nd.ivk);
1655 if (!optNote) {
1656 assert(false);
1657 }
1658 auto optNullifier = optNote.get().nullifier(fvk, position);
1659 if (!optNullifier) {
1660 // This should not happen. If it does, maybe the position has been corrupted or miscalculated?
1661 assert(false);
1662 }
1663 uint256 nullifier = optNullifier.get();
1664 mapSaplingNullifiersToNotes[nullifier] = op;
1665 item.second.nullifier = nullifier;
1666 }
1667 }
1668}
1669
1670/**
1671 * Iterate over transactions in a block and update the cached Sapling nullifiers
1672 * for transactions which belong to the wallet.
1673 */
1674void CWallet::UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock) {
1675 LOCK(cs_wallet);
1676
1677 for (const CTransaction& tx : pblock->vtx) {
1678 auto hash = tx.GetHash();
1679 bool txIsOurs = mapWallet.count(hash);
1680 if (txIsOurs) {
1681 UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]);
1682 }
8db7e25c
JG
1683 }
1684}
1685
44bc988e 1686bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
e8ef3da7 1687{
805344dc 1688 uint256 hash = wtxIn.GetHash();
731b89b8
GA
1689
1690 if (fFromLoadWallet)
1691 {
1692 mapWallet[hash] = wtxIn;
09ec3af1 1693 mapWallet[hash].BindWallet(this);
6e263a5f 1694 UpdateNullifierNoteMapWithTx(mapWallet[hash]);
93a18a36 1695 AddToSpends(hash);
731b89b8
GA
1696 }
1697 else
e8ef3da7 1698 {
f8dcd5ca 1699 LOCK(cs_wallet);
e8ef3da7
WL
1700 // Inserts only if not already there, returns tx inserted or tx found
1701 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
1702 CWalletTx& wtx = (*ret.first).second;
4c6e2295 1703 wtx.BindWallet(this);
6e263a5f 1704 UpdateNullifierNoteMapWithTx(wtx);
e8ef3da7
WL
1705 bool fInsertedNew = ret.second;
1706 if (fInsertedNew)
9c7722b7 1707 {
e8ef3da7 1708 wtx.nTimeReceived = GetAdjustedTime();
44bc988e 1709 wtx.nOrderPos = IncOrderPosNext(pwalletdb);
c3f95ef1
LD
1710
1711 wtx.nTimeSmart = wtx.nTimeReceived;
4f152496 1712 if (!wtxIn.hashBlock.IsNull())
c3f95ef1
LD
1713 {
1714 if (mapBlockIndex.count(wtxIn.hashBlock))
1715 {
209377a7 1716 int64_t latestNow = wtx.nTimeReceived;
1717 int64_t latestEntry = 0;
c3f95ef1
LD
1718 {
1719 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
51ed9ec9 1720 int64_t latestTolerated = latestNow + 300;
ddb709e9
LD
1721 std::list<CAccountingEntry> acentries;
1722 TxItems txOrdered = OrderedTxItems(acentries);
c3f95ef1
LD
1723 for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1724 {
1725 CWalletTx *const pwtx = (*it).second.first;
1726 if (pwtx == &wtx)
1727 continue;
1728 CAccountingEntry *const pacentry = (*it).second.second;
51ed9ec9 1729 int64_t nSmartTime;
c3f95ef1
LD
1730 if (pwtx)
1731 {
1732 nSmartTime = pwtx->nTimeSmart;
1733 if (!nSmartTime)
1734 nSmartTime = pwtx->nTimeReceived;
1735 }
1736 else
1737 nSmartTime = pacentry->nTime;
1738 if (nSmartTime <= latestTolerated)
1739 {
1740 latestEntry = nSmartTime;
1741 if (nSmartTime > latestNow)
1742 latestNow = nSmartTime;
1743 break;
1744 }
1745 }
1746 }
1747
209377a7 1748 int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
c3f95ef1
LD
1749 wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
1750 }
1751 else
5262fde0 1752 LogPrintf("AddToWallet(): found %s in block %s not in index\n",
805344dc 1753 wtxIn.GetHash().ToString(),
7d9d134b 1754 wtxIn.hashBlock.ToString());
c3f95ef1 1755 }
93a18a36 1756 AddToSpends(hash);
9c7722b7 1757 }
e8ef3da7
WL
1758
1759 bool fUpdated = false;
1760 if (!fInsertedNew)
1761 {
1762 // Merge
4f152496 1763 if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
e8ef3da7
WL
1764 {
1765 wtx.hashBlock = wtxIn.hashBlock;
1766 fUpdated = true;
1767 }
1768 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
1769 {
1770 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
1771 wtx.nIndex = wtxIn.nIndex;
1772 fUpdated = true;
1773 }
ac1c9435 1774 if (UpdatedNoteData(wtxIn, wtx)) {
c3a7307a
JG
1775 fUpdated = true;
1776 }
e8ef3da7
WL
1777 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
1778 {
1779 wtx.fFromMe = wtxIn.fFromMe;
1780 fUpdated = true;
1781 }
e8ef3da7
WL
1782 }
1783
1784 //// debug print
805344dc 1785 LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
e8ef3da7
WL
1786
1787 // Write to disk
1788 if (fInsertedNew || fUpdated)
44bc988e 1789 if (!wtx.WriteToDisk(pwalletdb))
e8ef3da7 1790 return false;
ee4b170c 1791
93a18a36
GA
1792 // Break debit/credit balance caches:
1793 wtx.MarkDirty();
e8ef3da7 1794
fe4a6550
WL
1795 // Notify UI of new or updated transaction
1796 NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
cae686d3 1797
1798 // notify an external script when a wallet transaction comes in or is updated
1799 std::string strCmd = GetArg("-walletnotify", "");
1800
1801 if ( !strCmd.empty())
1802 {
805344dc 1803 boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
cae686d3 1804 boost::thread t(runCommand, strCmd); // thread runs free
1805 }
1806
fe4a6550 1807 }
e8ef3da7
WL
1808 return true;
1809}
1810
ac1c9435
JG
1811bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
1812{
3a83e7c9
S
1813 bool unchangedSproutFlag = (wtxIn.mapSproutNoteData.empty() || wtxIn.mapSproutNoteData == wtx.mapSproutNoteData);
1814 if (!unchangedSproutFlag) {
1815 auto tmp = wtxIn.mapSproutNoteData;
1816 // Ensure we keep any cached witnesses we may already have
1817 for (const std::pair <JSOutPoint, SproutNoteData> nd : wtx.mapSproutNoteData) {
1818 if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
1819 tmp.at(nd.first).witnesses.assign(
1820 nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
1821 }
1822 tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
1823 }
1824 // Now copy over the updated note data
1825 wtx.mapSproutNoteData = tmp;
ac1c9435 1826 }
3a83e7c9
S
1827
1828 bool unchangedSaplingFlag = (wtxIn.mapSaplingNoteData.empty() || wtxIn.mapSaplingNoteData == wtx.mapSaplingNoteData);
1829 if (!unchangedSaplingFlag) {
1830 auto tmp = wtxIn.mapSaplingNoteData;
1831 // Ensure we keep any cached witnesses we may already have
1832
1833 for (const std::pair <SaplingOutPoint, SaplingNoteData> nd : wtx.mapSaplingNoteData) {
1834 if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
1835 tmp.at(nd.first).witnesses.assign(
1836 nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
1837 }
1838 tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
ac1c9435 1839 }
3a83e7c9
S
1840
1841 // Now copy over the updated note data
1842 wtx.mapSaplingNoteData = tmp;
ac1c9435 1843 }
3a83e7c9
S
1844
1845 return !unchangedSproutFlag || !unchangedSaplingFlag;
ac1c9435
JG
1846}
1847
5b40d886
MF
1848/**
1849 * Add a transaction to the wallet, or update it.
1850 * pblock is optional, but should be provided if the transaction is known to be in a block.
1851 * If fUpdate is true, existing transactions will be updated.
1852 */
d38da59b 1853bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
e8ef3da7 1854{
e8ef3da7 1855 {
53d56881 1856 AssertLockHeld(cs_wallet);
805344dc 1857 bool fExisted = mapWallet.count(tx.GetHash()) != 0;
6cc4a62c 1858 if (fExisted && !fUpdate) return false;
78584ef7 1859 auto sproutNoteData = FindMySproutNotes(tx);
a4ecd0fa
EOW
1860 auto saplingNoteDataAndAddressesToAdd = FindMySaplingNotes(tx);
1861 auto saplingNoteData = saplingNoteDataAndAddressesToAdd.first;
1862 auto addressesToAdd = saplingNoteDataAndAddressesToAdd.second;
1863 for (const auto &addressToAdd : addressesToAdd) {
1864 if (!AddSaplingIncomingViewingKey(addressToAdd.second, addressToAdd.first)) {
1865 return false;
1866 }
1867 }
78584ef7 1868 if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0)
6cc4a62c
GA
1869 {
1870 CWalletTx wtx(this,tx);
44bc988e 1871
78584ef7
S
1872 if (sproutNoteData.size() > 0) {
1873 wtx.SetSproutNoteData(sproutNoteData);
1874 }
1875
1876 if (saplingNoteData.size() > 0) {
1877 wtx.SetSaplingNoteData(saplingNoteData);
be74c80d 1878 }
c3a7307a 1879
6cc4a62c
GA
1880 // Get merkle branch if transaction was found in a block
1881 if (pblock)
4b0deb3b 1882 wtx.SetMerkleBranch(*pblock);
44bc988e
CL
1883
1884 // Do not flush the wallet here for performance reasons
1885 // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
1886 CWalletDB walletdb(strWalletFile, "r+", false);
1887
1888 return AddToWallet(wtx, false, &walletdb);
6cc4a62c 1889 }
e8ef3da7 1890 }
e8ef3da7
WL
1891 return false;
1892}
1893
d38da59b 1894void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
93a18a36 1895{
55a1db4f 1896 LOCK2(cs_main, cs_wallet);
d38da59b 1897 if (!AddToWalletIfInvolvingMe(tx, pblock, true))
93a18a36
GA
1898 return; // Not one of ours
1899
ac1c9435
JG
1900 MarkAffectedTransactionsDirty(tx);
1901}
1902
1903void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx)
1904{
93a18a36
GA
1905 // If a transaction changes 'conflicted' state, that changes the balance
1906 // available of the outputs it spends. So force those to be
1907 // recomputed, also:
1908 BOOST_FOREACH(const CTxIn& txin, tx.vin)
1909 {
1910 if (mapWallet.count(txin.prevout.hash))
1911 mapWallet[txin.prevout.hash].MarkDirty();
1912 }
8db7e25c
JG
1913 for (const JSDescription& jsdesc : tx.vjoinsplit) {
1914 for (const uint256& nullifier : jsdesc.nullifiers) {
f41bf503 1915 if (mapSproutNullifiersToNotes.count(nullifier) &&
dae1c420 1916 mapWallet.count(mapSproutNullifiersToNotes[nullifier].hash)) {
f41bf503 1917 mapWallet[mapSproutNullifiersToNotes[nullifier].hash].MarkDirty();
8db7e25c
JG
1918 }
1919 }
1920 }
dae1c420
S
1921
1922 for (const SpendDescription &spend : tx.vShieldedSpend) {
1923 uint256 nullifier = spend.nullifier;
1924 if (mapSaplingNullifiersToNotes.count(nullifier) &&
1925 mapWallet.count(mapSaplingNullifiersToNotes[nullifier].hash)) {
1926 mapWallet[mapSaplingNullifiersToNotes[nullifier].hash].MarkDirty();
1927 }
1928 }
00588c3f
PW
1929}
1930
1931void CWallet::EraseFromWallet(const uint256 &hash)
e8ef3da7
WL
1932{
1933 if (!fFileBacked)
00588c3f 1934 return;
e8ef3da7 1935 {
f8dcd5ca 1936 LOCK(cs_wallet);
e8ef3da7
WL
1937 if (mapWallet.erase(hash))
1938 CWalletDB(strWalletFile).EraseTx(hash);
1939 }
00588c3f 1940 return;
e8ef3da7
WL
1941}
1942
47ab0926 1943void CWallet::RescanWallet()
1944{
1945 if (needsRescan)
1946 {
1947 CBlockIndex *start = chainActive.Height() > 0 ? chainActive[1] : NULL;
1948 if (start)
1949 ScanForWalletTransactions(start, true);
1950 needsRescan = false;
1951 }
1952}
1953
e8ef3da7 1954
1a62587e
JG
1955/**
1956 * Returns a nullifier if the SpendingKey is available
1957 * Throws std::runtime_error if the decryptor doesn't match this note
1958 */
618206c7
S
1959boost::optional<uint256> CWallet::GetSproutNoteNullifier(const JSDescription &jsdesc,
1960 const libzcash::SproutPaymentAddress &address,
1961 const ZCNoteDecryption &dec,
1962 const uint256 &hSig,
1963 uint8_t n) const
1a62587e
JG
1964{
1965 boost::optional<uint256> ret;
5020a936 1966 auto note_pt = libzcash::SproutNotePlaintext::decrypt(
1a62587e
JG
1967 dec,
1968 jsdesc.ciphertexts[n],
1969 jsdesc.ephemeralKey,
1970 hSig,
1971 (unsigned char) n);
1972 auto note = note_pt.note(address);
9a2b8ae5
JG
1973 // SpendingKeys are only available if:
1974 // - We have them (this isn't a viewing key)
1975 // - The wallet is unlocked
e5eab182 1976 libzcash::SproutSpendingKey key;
25d5e80c 1977 if (GetSproutSpendingKey(address, key)) {
1a62587e
JG
1978 ret = note.nullifier(key);
1979 }
1980 return ret;
1981}
1982
e492d986
JG
1983/**
1984 * Finds all output notes in the given transaction that have been sent to
1985 * PaymentAddresses in this wallet.
1986 *
1987 * It should never be necessary to call this method with a CWalletTx, because
57faf44e 1988 * the result of FindMySproutNotes (for the addresses available at the time) will
005f3ad1 1989 * already have been cached in CWalletTx.mapSproutNoteData.
e492d986 1990 */
57faf44e 1991mapSproutNoteData_t CWallet::FindMySproutNotes(const CTransaction &tx) const
02e67455 1992{
3fac1020 1993 LOCK(cs_SpendingKeyStore);
fa511e10 1994 uint256 hash = tx.GetHash();
02e67455 1995
005f3ad1 1996 mapSproutNoteData_t noteData;
02e67455
JG
1997 for (size_t i = 0; i < tx.vjoinsplit.size(); i++) {
1998 auto hSig = tx.vjoinsplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey);
1999 for (uint8_t j = 0; j < tx.vjoinsplit[i].ciphertexts.size(); j++) {
3fac1020 2000 for (const NoteDecryptorMap::value_type& item : mapNoteDecryptors) {
02e67455 2001 try {
02e67455 2002 auto address = item.first;
02e67455 2003 JSOutPoint jsoutpt {hash, i, j};
618206c7 2004 auto nullifier = GetSproutNoteNullifier(
1a62587e
JG
2005 tx.vjoinsplit[i],
2006 address,
2007 item.second,
2008 hSig, j);
2009 if (nullifier) {
005f3ad1 2010 SproutNoteData nd {address, *nullifier};
1a62587e
JG
2011 noteData.insert(std::make_pair(jsoutpt, nd));
2012 } else {
005f3ad1 2013 SproutNoteData nd {address};
1a62587e
JG
2014 noteData.insert(std::make_pair(jsoutpt, nd));
2015 }
02e67455 2016 break;
51fde9ea 2017 } catch (const note_decryption_failed &err) {
1a62587e 2018 // Couldn't decrypt with this decryptor
32a103aa
JG
2019 } catch (const std::exception &exc) {
2020 // Unexpected failure
57faf44e 2021 LogPrintf("FindMySproutNotes(): Unexpected error while testing decrypt:\n");
32a103aa 2022 LogPrintf("%s\n", exc.what());
02e67455
JG
2023 }
2024 }
2025 }
2026 }
2027 return noteData;
2028}
2029
78584ef7
S
2030
2031/**
2032 * Finds all output notes in the given transaction that have been sent to
2033 * SaplingPaymentAddresses in this wallet.
2034 *
2035 * It should never be necessary to call this method with a CWalletTx, because
2036 * the result of FindMySaplingNotes (for the addresses available at the time) will
2037 * already have been cached in CWalletTx.mapSaplingNoteData.
2038 */
a4ecd0fa 2039std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySaplingNotes(const CTransaction &tx) const
78584ef7
S
2040{
2041 LOCK(cs_SpendingKeyStore);
2042 uint256 hash = tx.GetHash();
2043
2044 mapSaplingNoteData_t noteData;
a4ecd0fa 2045 SaplingIncomingViewingKeyMap viewingKeysToAdd;
78584ef7
S
2046
2047 // Protocol Spec: 4.19 Block Chain Scanning (Sapling)
2048 for (uint32_t i = 0; i < tx.vShieldedOutput.size(); ++i) {
2049 const OutputDescription output = tx.vShieldedOutput[i];
ec064abb
S
2050 for (auto it = mapSaplingFullViewingKeys.begin(); it != mapSaplingFullViewingKeys.end(); ++it) {
2051 SaplingIncomingViewingKey ivk = it->first;
78584ef7
S
2052 auto result = SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cm);
2053 if (!result) {
2054 continue;
2055 }
a4ecd0fa
EOW
2056 auto address = ivk.address(result.get().d);
2057 if (address && mapSaplingIncomingViewingKeys.count(address.get()) == 0) {
2058 viewingKeysToAdd[address.get()] = ivk;
2059 }
78584ef7
S
2060 // We don't cache the nullifier here as computing it requires knowledge of the note position
2061 // in the commitment tree, which can only be determined when the transaction has been mined.
2062 SaplingOutPoint op {hash, i};
2063 SaplingNoteData nd;
2064 nd.ivk = ivk;
2065 noteData.insert(std::make_pair(op, nd));
2066 break;
2067 }
2068 }
2069
a4ecd0fa 2070 return std::make_pair(noteData, viewingKeysToAdd);
78584ef7
S
2071}
2072
037cacf2 2073bool CWallet::IsSproutNullifierFromMe(const uint256& nullifier) const
1551db87
JG
2074{
2075 {
2076 LOCK(cs_wallet);
f41bf503
S
2077 if (mapSproutNullifiersToNotes.count(nullifier) &&
2078 mapWallet.count(mapSproutNullifiersToNotes.at(nullifier).hash)) {
1551db87
JG
2079 return true;
2080 }
2081 }
2082 return false;
2083}
2084
d7cf640b 2085bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const
be74c80d
JG
2086{
2087 {
2088 LOCK(cs_wallet);
d7cf640b
S
2089 if (mapSaplingNullifiersToNotes.count(nullifier) &&
2090 mapWallet.count(mapSaplingNullifiersToNotes.at(nullifier).hash)) {
2091 return true;
2092 }
2093 }
2094 return false;
2095}
2096
8e8279e7 2097void CWallet::GetSproutNoteWitnesses(std::vector<JSOutPoint> notes,
8ea8ef98 2098 std::vector<boost::optional<SproutWitness>>& witnesses,
8e8279e7 2099 uint256 &final_anchor)
be74c80d 2100{
29523dc7
EOW
2101 LOCK(cs_wallet);
2102 witnesses.resize(notes.size());
2103 boost::optional<uint256> rt;
2104 int i = 0;
2105 for (JSOutPoint note : notes) {
2106 if (mapWallet.count(note.hash) &&
2107 mapWallet[note.hash].mapSproutNoteData.count(note) &&
2108 mapWallet[note.hash].mapSproutNoteData[note].witnesses.size() > 0) {
2109 witnesses[i] = mapWallet[note.hash].mapSproutNoteData[note].witnesses.front();
2110 if (!rt) {
2111 rt = witnesses[i]->root();
2112 } else {
2113 assert(*rt == witnesses[i]->root());
be74c80d 2114 }
be74c80d 2115 }
29523dc7
EOW
2116 i++;
2117 }
2118 // All returned witnesses have the same anchor
2119 if (rt) {
2120 final_anchor = *rt;
be74c80d
JG
2121 }
2122}
2123
e6b0a8b9 2124void CWallet::GetSaplingNoteWitnesses(std::vector<SaplingOutPoint> notes,
8ea8ef98 2125 std::vector<boost::optional<SaplingWitness>>& witnesses,
e6b0a8b9
EOW
2126 uint256 &final_anchor)
2127{
2128 LOCK(cs_wallet);
2129 witnesses.resize(notes.size());
2130 boost::optional<uint256> rt;
2131 int i = 0;
2132 for (SaplingOutPoint note : notes) {
2133 if (mapWallet.count(note.hash) &&
2134 mapWallet[note.hash].mapSaplingNoteData.count(note) &&
2135 mapWallet[note.hash].mapSaplingNoteData[note].witnesses.size() > 0) {
2136 witnesses[i] = mapWallet[note.hash].mapSaplingNoteData[note].witnesses.front();
2137 if (!rt) {
2138 rt = witnesses[i]->root();
2139 } else {
2140 assert(*rt == witnesses[i]->root());
2141 }
be74c80d 2142 }
e6b0a8b9
EOW
2143 i++;
2144 }
2145 // All returned witnesses have the same anchor
2146 if (rt) {
2147 final_anchor = *rt;
be74c80d
JG
2148 }
2149}
2150
c8988460 2151isminetype CWallet::IsMine(const CTxIn &txin) const
e8ef3da7 2152{
e8ef3da7 2153 {
f8dcd5ca 2154 LOCK(cs_wallet);
e8ef3da7
WL
2155 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
2156 if (mi != mapWallet.end())
2157 {
2158 const CWalletTx& prev = (*mi).second;
2159 if (txin.prevout.n < prev.vout.size())
ea340a14 2160 return (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey));
e8ef3da7
WL
2161 }
2162 }
a3e192a3 2163 return ISMINE_NO;
e8ef3da7
WL
2164}
2165
a372168e 2166CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
e8ef3da7 2167{
e8ef3da7 2168 {
f8dcd5ca 2169 LOCK(cs_wallet);
e8ef3da7
WL
2170 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
2171 if (mi != mapWallet.end())
2172 {
2173 const CWalletTx& prev = (*mi).second;
2174 if (txin.prevout.n < prev.vout.size())
ea340a14 2175 if (::IsMine(*this, prev.vout[txin.prevout.n].scriptPubKey) & filter)
47658758 2176 return prev.vout[txin.prevout.n].nValue; // komodo_interest?
e8ef3da7
WL
2177 }
2178 }
2179 return 0;
2180}
2181
eca0b1ea
JT
2182isminetype CWallet::IsMine(const CTxOut& txout) const
2183{
2184 return ::IsMine(*this, txout.scriptPubKey);
2185}
2186
2187CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
2188{
2189 if (!MoneyRange(txout.nValue))
2190 throw std::runtime_error("CWallet::GetCredit(): value out of range");
2191 return ((IsMine(txout) & filter) ? txout.nValue : 0);
2192}
2193
e679ec96
GA
2194bool CWallet::IsChange(const CTxOut& txout) const
2195{
2a45a494 2196 // TODO: fix handling of 'change' outputs. The assumption is that any
d5087d1b 2197 // payment to a script that is ours, but is not in the address book
2a45a494
GA
2198 // is change. That assumption is likely to break when we implement multisignature
2199 // wallets that return change back into a multi-signature-protected address;
2200 // a better way of identifying which outputs are 'the send' and which are
2201 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
2202 // which output, if any, was change).
d5087d1b 2203 if (::IsMine(*this, txout.scriptPubKey))
f8dcd5ca 2204 {
d5087d1b
PW
2205 CTxDestination address;
2206 if (!ExtractDestination(txout.scriptPubKey, address))
2207 return true;
2208
f8dcd5ca
PW
2209 LOCK(cs_wallet);
2210 if (!mapAddressBook.count(address))
2211 return true;
2212 }
e679ec96
GA
2213 return false;
2214}
2215
eca0b1ea
JT
2216CAmount CWallet::GetChange(const CTxOut& txout) const
2217{
2218 if (!MoneyRange(txout.nValue))
2219 throw std::runtime_error("CWallet::GetChange(): value out of range");
2220 return (IsChange(txout) ? txout.nValue : 0);
2221}
2222
ea340a14 2223typedef vector<unsigned char> valtype;
2224unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore);
2225
90e75021 2226bool CWallet::IsMine(const CTransaction& tx)
eca0b1ea 2227{
90e75021 2228 for (int i = 0; i < tx.vout.size(); i++)
2229 {
1a0fc308 2230 if (IsMine(tx, i))
eca0b1ea 2231 return true;
90e75021 2232 }
2233 return false;
2234}
2235
29bd53a1
MT
2236// special case handling for non-standard/Verus OP_RETURN script outputs, which need the transaction
2237// to determine ownership
ea340a14 2238isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum)
29bd53a1
MT
2239{
2240 vector<valtype> vSolutions;
2241 txnouttype whichType;
2242 const CScriptExt scriptPubKey = CScriptExt(tx.vout[voutNum].scriptPubKey);
2243
2244 if (!Solver(scriptPubKey, whichType, vSolutions)) {
2245 if (this->HaveWatchOnly(scriptPubKey))
2246 return ISMINE_WATCH_ONLY;
2247 return ISMINE_NO;
2248 }
2249
2250 CKeyID keyID;
90e75021 2251 CScriptID scriptID;
29bd53a1
MT
2252 CScriptExt subscript;
2253 int voutNext = voutNum + 1;
2254
2255 switch (whichType)
2256 {
2257 case TX_NONSTANDARD:
2258 case TX_NULL_DATA:
2259 break;
2260
68b9a352 2261 case TX_CRYPTOCONDITION:
2262 // for now, default is that the first value returned will be the script, subsequent values will be
2263 // pubkeys. if we have the first pub key in our wallet, we consider this spendable
2264 if (vSolutions.size() > 1)
2265 {
2266 keyID = CPubKey(vSolutions[1]).GetID();
2267 if (this->HaveKey(keyID))
2268 return ISMINE_SPENDABLE;
2269 }
2270 break;
2271
29bd53a1
MT
2272 case TX_PUBKEY:
2273 keyID = CPubKey(vSolutions[0]).GetID();
2274 if (this->HaveKey(keyID))
2275 return ISMINE_SPENDABLE;
2276 break;
2277
2278 case TX_PUBKEYHASH:
2279 keyID = CKeyID(uint160(vSolutions[0]));
2280 if (this->HaveKey(keyID))
2281 return ISMINE_SPENDABLE;
2282 break;
2283
2284 case TX_SCRIPTHASH:
90e75021 2285 scriptID = CScriptID(uint160(vSolutions[0]));
29bd53a1
MT
2286 if (this->GetCScript(scriptID, subscript))
2287 {
2288 // if this is a CLTV, handle it differently
ef70c5b2 2289 if (subscript.IsCheckLockTimeVerify())
29bd53a1 2290 {
ea340a14 2291 return (::IsMine(*this, subscript));
29bd53a1
MT
2292 }
2293 else
2294 {
2295 isminetype ret = ::IsMine(*this, subscript);
2296 if (ret == ISMINE_SPENDABLE)
2297 return ret;
2298 }
2299 }
2300 else if (tx.vout.size() > (voutNext = voutNum + 1) &&
2301 tx.vout[voutNext].scriptPubKey.size() > 7 &&
9feb4b9e 2302 tx.vout[voutNext].scriptPubKey[0] == OP_RETURN)
29bd53a1
MT
2303 {
2304 // get the opret script from next vout, verify that the front is CLTV and hash matches
2305 // if so, remove it and use the solver
2306 opcodetype op;
2307 std::vector<uint8_t> opretData;
2308 CScript::const_iterator it = tx.vout[voutNext].scriptPubKey.begin() + 1;
2309 if (tx.vout[voutNext].scriptPubKey.GetOp2(it, op, &opretData))
2310 {
9feb4b9e 2311 if (opretData.size() > 0 && opretData[0] == OPRETTYPE_TIMELOCK)
29bd53a1 2312 {
9feb4b9e 2313 CScript opretScript = CScript(opretData.begin() + 1, opretData.end());
29bd53a1
MT
2314
2315 if (CScriptID(opretScript) == scriptID &&
ef70c5b2 2316 opretScript.IsCheckLockTimeVerify())
29bd53a1 2317 {
ea340a14 2318 // if we find that this is ours, we need to add this script to the wallet,
2319 // and we can then recognize this transaction
2320 isminetype t = ::IsMine(*this, opretScript);
2321 if (t != ISMINE_NO)
2322 {
2323 this->AddCScript(opretScript);
2324 }
2325 return t;
29bd53a1
MT
2326 }
2327 }
2328 }
2329 }
2330 break;
2331
2332 case TX_MULTISIG:
2333 // Only consider transactions "mine" if we own ALL the
2334 // keys involved. Multi-signature transactions that are
2335 // partially owned (somebody else has a key that can spend
2336 // them) enable spend-out-from-under-you attacks, especially
2337 // in shared-wallet situations.
2338 vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
2339 if (HaveKeys(keys, *this) == keys.size())
2340 return ISMINE_SPENDABLE;
2341 break;
2342 }
2343
2344 if (this->HaveWatchOnly(scriptPubKey))
2345 return ISMINE_WATCH_ONLY;
2346
2347 return ISMINE_NO;
2348}
2349
eca0b1ea
JT
2350bool CWallet::IsFromMe(const CTransaction& tx) const
2351{
1551db87
JG
2352 if (GetDebit(tx, ISMINE_ALL) > 0) {
2353 return true;
2354 }
2355 for (const JSDescription& jsdesc : tx.vjoinsplit) {
2356 for (const uint256& nullifier : jsdesc.nullifiers) {
037cacf2 2357 if (IsSproutNullifierFromMe(nullifier)) {
1551db87
JG
2358 return true;
2359 }
2360 }
2361 }
d7cf640b
S
2362 for (const SpendDescription &spend : tx.vShieldedSpend) {
2363 if (IsSaplingNullifierFromMe(spend.nullifier)) {
2364 return true;
2365 }
2366 }
1551db87 2367 return false;
eca0b1ea
JT
2368}
2369
2370CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
2371{
2372 CAmount nDebit = 0;
2373 BOOST_FOREACH(const CTxIn& txin, tx.vin)
2374 {
2375 nDebit += GetDebit(txin, filter);
2376 if (!MoneyRange(nDebit))
2377 throw std::runtime_error("CWallet::GetDebit(): value out of range");
2378 }
2379 return nDebit;
2380}
2381
fab1429d 2382CAmount CWallet::GetCredit(const CTransaction& tx, int32_t voutNum, const isminefilter& filter) const
2383{
2384 if (voutNum >= tx.vout.size() || !MoneyRange(tx.vout[voutNum].nValue))
2385 throw std::runtime_error("CWallet::GetCredit(): value out of range");
ea340a14 2386 return ((IsMine(tx.vout[voutNum]) & filter) ? tx.vout[voutNum].nValue : 0);
fab1429d 2387}
2388
eca0b1ea
JT
2389CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const
2390{
2391 CAmount nCredit = 0;
fab1429d 2392 for (int i = 0; i < tx.vout.size(); i++)
eca0b1ea 2393 {
fab1429d 2394 nCredit += GetCredit(tx, i, filter);
eca0b1ea
JT
2395 }
2396 return nCredit;
2397}
2398
2399CAmount CWallet::GetChange(const CTransaction& tx) const
2400{
2401 CAmount nChange = 0;
2402 BOOST_FOREACH(const CTxOut& txout, tx.vout)
2403 {
2404 nChange += GetChange(txout);
2405 if (!MoneyRange(nChange))
2406 throw std::runtime_error("CWallet::GetChange(): value out of range");
2407 }
2408 return nChange;
2409}
2410
e2416930
JG
2411bool CWallet::IsHDFullyEnabled() const
2412{
2413 // Only Sapling addresses are HD for now
2414 return false;
2415}
2416
2417void CWallet::GenerateNewSeed()
2418{
2419 LOCK(cs_wallet);
2420
2421 auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
2422
2423 int64_t nCreationTime = GetTime();
2424
2425 // If the wallet is encrypted and locked, this will fail.
2426 if (!SetHDSeed(seed))
2427 throw std::runtime_error(std::string(__func__) + ": SetHDSeed failed");
2428
2429 // store the key creation time together with
2430 // the child index counter in the database
2431 // as a hdchain object
2432 CHDChain newHdChain;
2433 newHdChain.nVersion = CHDChain::VERSION_HD_BASE;
2434 newHdChain.seedFp = seed.Fingerprint();
2435 newHdChain.nCreateTime = nCreationTime;
2436 SetHDChain(newHdChain, false);
2437}
2438
2439bool CWallet::SetHDSeed(const HDSeed& seed)
c3a7307a 2440{
e2416930
JG
2441 if (!CCryptoKeyStore::SetHDSeed(seed)) {
2442 return false;
2443 }
2444
2445 if (!fFileBacked) {
2446 return true;
2447 }
2448
2449 {
2450 LOCK(cs_wallet);
2451 if (!IsCrypted()) {
2452 return CWalletDB(strWalletFile).WriteHDSeed(seed);
2453 }
2454 }
2455 return true;
2456}
2457
2458bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
2459{
2460 if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
2461 return false;
2462 }
2463
2464 if (!fFileBacked) {
2465 return true;
2466 }
2467
2468 {
2469 LOCK(cs_wallet);
2470 if (pwalletdbEncryption)
2471 return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
2472 else
2473 return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
2474 }
2475 return false;
2476}
2477
2478void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
2479{
2480 LOCK(cs_wallet);
2481 if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
2482 throw std::runtime_error(std::string(__func__) + ": writing chain failed");
2483
2484 hdChain = chain;
2485}
2486
2487bool CWallet::LoadHDSeed(const HDSeed& seed)
2488{
2489 return CBasicKeyStore::SetHDSeed(seed);
2490}
2491
2492bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
2493{
2494 return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
2495}
2496
8e8279e7 2497void CWalletTx::SetSproutNoteData(mapSproutNoteData_t &noteData)
c3a7307a 2498{
005f3ad1
EOW
2499 mapSproutNoteData.clear();
2500 for (const std::pair<JSOutPoint, SproutNoteData> nd : noteData) {
c3a7307a
JG
2501 if (nd.first.js < vjoinsplit.size() &&
2502 nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) {
2503 // Store the address and nullifier for the Note
005f3ad1 2504 mapSproutNoteData[nd.first] = nd.second;
c3a7307a 2505 } else {
57faf44e 2506 // If FindMySproutNotes() was used to obtain noteData,
c3a7307a 2507 // this should never happen
8e8279e7 2508 throw std::logic_error("CWalletTx::SetSproutNoteData(): Invalid note");
c3a7307a
JG
2509 }
2510 }
2511}
2512
e6b0a8b9
EOW
2513void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t &noteData)
2514{
2515 mapSaplingNoteData.clear();
2516 for (const std::pair<SaplingOutPoint, SaplingNoteData> nd : noteData) {
2517 if (nd.first.n < vShieldedOutput.size()) {
2518 mapSaplingNoteData[nd.first] = nd.second;
2519 } else {
2520 throw std::logic_error("CWalletTx::SetSaplingNoteData(): Invalid note");
c3a7307a
JG
2521 }
2522 }
2523}
2524
51ed9ec9 2525int64_t CWalletTx::GetTxTime() const
e8ef3da7 2526{
51ed9ec9 2527 int64_t n = nTimeSmart;
c3f95ef1 2528 return n ? n : nTimeReceived;
e8ef3da7
WL
2529}
2530
2531int CWalletTx::GetRequestCount() const
2532{
2533 // Returns -1 if it wasn't being tracked
2534 int nRequests = -1;
e8ef3da7 2535 {
f8dcd5ca 2536 LOCK(pwallet->cs_wallet);
e8ef3da7
WL
2537 if (IsCoinBase())
2538 {
2539 // Generated block
4f152496 2540 if (!hashBlock.IsNull())
e8ef3da7
WL
2541 {
2542 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
2543 if (mi != pwallet->mapRequestCount.end())
2544 nRequests = (*mi).second;
2545 }
2546 }
2547 else
2548 {
2549 // Did anyone request this transaction?
805344dc 2550 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
e8ef3da7
WL
2551 if (mi != pwallet->mapRequestCount.end())
2552 {
2553 nRequests = (*mi).second;
2554
2555 // How about the block it's in?
4f152496 2556 if (nRequests == 0 && !hashBlock.IsNull())
e8ef3da7
WL
2557 {
2558 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
2559 if (mi != pwallet->mapRequestCount.end())
2560 nRequests = (*mi).second;
2561 else
2562 nRequests = 1; // If it's in someone else's block it must have got out
2563 }
2564 }
2565 }
2566 }
2567 return nRequests;
2568}
2569
86cf60b5 2570// GetAmounts will determine the transparent debits and credits for a given wallet tx.
1b4568cb 2571void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
a372168e 2572 list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
e8ef3da7 2573{
e07c8e91 2574 nFee = 0;
e8ef3da7
WL
2575 listReceived.clear();
2576 listSent.clear();
2577 strSentAccount = strFromAccount;
2578
86cf60b5 2579 // Is this tx sent/signed by me?
a372168e 2580 CAmount nDebit = GetDebit(filter);
86cf60b5
S
2581 bool isFromMyTaddr = nDebit > 0; // debit>0 means we signed/sent this transaction
2582
86cf60b5
S
2583 // Compute fee if we sent this transaction.
2584 if (isFromMyTaddr) {
f6863889
S
2585 CAmount nValueOut = GetValueOut(); // transparent outputs plus all Sprout vpub_old and negative Sapling valueBalance
2586 CAmount nValueIn = GetShieldedValueIn();
86cf60b5
S
2587 nFee = nDebit - nValueOut + nValueIn;
2588 }
2589
2590 // Create output entry for vpub_old/new, if we sent utxos from this transaction
2591 if (isFromMyTaddr) {
2592 CAmount myVpubOld = 0;
2593 CAmount myVpubNew = 0;
2594 for (const JSDescription& js : vjoinsplit) {
2595 bool fMyJSDesc = false;
2596
2597 // Check input side
2598 for (const uint256& nullifier : js.nullifiers) {
037cacf2 2599 if (pwallet->IsSproutNullifierFromMe(nullifier)) {
86cf60b5
S
2600 fMyJSDesc = true;
2601 break;
2602 }
2603 }
2604
2605 // Check output side
2606 if (!fMyJSDesc) {
005f3ad1 2607 for (const std::pair<JSOutPoint, SproutNoteData> nd : this->mapSproutNoteData) {
86cf60b5
S
2608 if (nd.first.js < vjoinsplit.size() && nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) {
2609 fMyJSDesc = true;
2610 break;
2611 }
2612 }
2613 }
2614
2615 if (fMyJSDesc) {
2616 myVpubOld += js.vpub_old;
2617 myVpubNew += js.vpub_new;
2618 }
2619
2620 if (!MoneyRange(js.vpub_old) || !MoneyRange(js.vpub_new) || !MoneyRange(myVpubOld) || !MoneyRange(myVpubNew)) {
2621 throw std::runtime_error("CWalletTx::GetAmounts: value out of range");
2622 }
2623 }
2624
2625 // Create an output for the value taken from or added to the transparent value pool by JoinSplits
2626 if (myVpubOld > myVpubNew) {
2627 COutputEntry output = {CNoDestination(), myVpubOld - myVpubNew, (int)vout.size()};
2628 listSent.push_back(output);
2629 } else if (myVpubNew > myVpubOld) {
2630 COutputEntry output = {CNoDestination(), myVpubNew - myVpubOld, (int)vout.size()};
2631 listReceived.push_back(output);
2632 }
e8ef3da7
WL
2633 }
2634
f9816408
S
2635 // If we sent utxos from this transaction, create output for value taken from (negative valueBalance)
2636 // or added (positive valueBalance) to the transparent value pool by Sapling shielding and unshielding.
2637 if (isFromMyTaddr) {
2638 if (valueBalance < 0) {
2639 COutputEntry output = {CNoDestination(), -valueBalance, (int) vout.size()};
2640 listSent.push_back(output);
2641 } else if (valueBalance > 0) {
2642 COutputEntry output = {CNoDestination(), valueBalance, (int) vout.size()};
2643 listReceived.push_back(output);
2644 }
2645 }
2646
e679ec96 2647 // Sent/received.
5bb76550 2648 for (unsigned int i = 0; i < vout.size(); ++i)
e8ef3da7 2649 {
1b4568cb 2650 const CTxOut& txout = vout[i];
a5c6c5d6 2651 isminetype fIsMine = pwallet->IsMine(txout);
96ed6821
LD
2652 // Only need to handle txouts if AT LEAST one of these is true:
2653 // 1) they debit from us (sent)
2654 // 2) the output is to us (received)
2655 if (nDebit > 0)
2656 {
2657 // Don't report 'change' txouts
73b4d696 2658 if (!(filter & ISMINE_CHANGE) && pwallet->IsChange(txout))
96ed6821 2659 continue;
96ed6821 2660 }
a5c6c5d6 2661 else if (!(fIsMine & filter))
96ed6821
LD
2662 continue;
2663
2664 // In either case, we need to get the destination address
10254401 2665 CTxDestination address;
10254401 2666 if (!ExtractDestination(txout.scriptPubKey, address))
e8ef3da7 2667 {
7d306d64 2668 //LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",this->GetHash().ToString()); complains on the opreturns
96ed6821 2669 address = CNoDestination();
e8ef3da7
WL
2670 }
2671
5bb76550 2672 COutputEntry output = {address, txout.nValue, (int)i};
1b4568cb 2673
96ed6821 2674 // If we are debited by the transaction, add the output as a "sent" entry
e8ef3da7 2675 if (nDebit > 0)
1b4568cb 2676 listSent.push_back(output);
e8ef3da7 2677
96ed6821 2678 // If we are receiving the output, add it as a "received" entry
d512534c 2679 if (fIsMine & filter)
1b4568cb 2680 listReceived.push_back(output);
e8ef3da7
WL
2681 }
2682
2683}
2684
a372168e
MF
2685void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
2686 CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
e8ef3da7 2687{
e07c8e91 2688 nReceived = nSent = nFee = 0;
e8ef3da7 2689
a372168e 2690 CAmount allFee;
e8ef3da7 2691 string strSentAccount;
1b4568cb
CL
2692 list<COutputEntry> listReceived;
2693 list<COutputEntry> listSent;
d4640d7d 2694 GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
e8ef3da7 2695
e8ef3da7
WL
2696 if (strAccount == strSentAccount)
2697 {
1b4568cb
CL
2698 BOOST_FOREACH(const COutputEntry& s, listSent)
2699 nSent += s.amount;
e8ef3da7
WL
2700 nFee = allFee;
2701 }
e8ef3da7 2702 {
f8dcd5ca 2703 LOCK(pwallet->cs_wallet);
1b4568cb 2704 BOOST_FOREACH(const COutputEntry& r, listReceived)
e8ef3da7 2705 {
1b4568cb 2706 if (pwallet->mapAddressBook.count(r.destination))
e8ef3da7 2707 {
1b4568cb 2708 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
61885513 2709 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
1b4568cb 2710 nReceived += r.amount;
e8ef3da7
WL
2711 }
2712 else if (strAccount.empty())
2713 {
1b4568cb 2714 nReceived += r.amount;
e8ef3da7
WL
2715 }
2716 }
2717 }
2718}
2719
722fa283 2720
44bc988e 2721bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
e8ef3da7 2722{
805344dc 2723 return pwalletdb->WriteTx(GetHash(), *this);
e8ef3da7
WL
2724}
2725
4bc00dc1 2726void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
8ea8ef98 2727 std::vector<boost::optional<SproutWitness>>& witnesses,
4bc00dc1 2728 uint256 &final_anchor)
a8ac403d 2729{
2dc35992 2730 witnesses.resize(commitments.size());
a8ac403d 2731 CBlockIndex* pindex = chainActive.Genesis();
4fc309f0 2732 SproutMerkleTree tree;
a8ac403d
SB
2733
2734 while (pindex) {
2735 CBlock block;
b8add6a4 2736 ReadBlockFromDisk(block, pindex,1);
a8ac403d
SB
2737
2738 BOOST_FOREACH(const CTransaction& tx, block.vtx)
2739 {
22de1602 2740 BOOST_FOREACH(const JSDescription& jsdesc, tx.vjoinsplit)
a8ac403d 2741 {
22de1602 2742 BOOST_FOREACH(const uint256 &note_commitment, jsdesc.commitments)
a8ac403d 2743 {
4bc00dc1 2744 tree.append(note_commitment);
1760b3cd 2745
8ea8ef98 2746 BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
2dc35992 2747 if (wit) {
4bc00dc1 2748 wit->append(note_commitment);
2dc35992
SB
2749 }
2750 }
2751
2752 size_t i = 0;
2753 BOOST_FOREACH(uint256& commitment, commitments) {
4bc00dc1 2754 if (note_commitment == commitment) {
2dc35992 2755 witnesses.at(i) = tree.witness();
1760b3cd 2756 }
2dc35992 2757 i++;
a8ac403d
SB
2758 }
2759 }
2760 }
2761 }
2762
ccb439c5 2763 uint256 current_anchor = tree.root();
a8ac403d
SB
2764
2765 // Consistency check: we should be able to find the current tree
2766 // in our CCoins view.
4fc309f0 2767 SproutMerkleTree dummy_tree;
008f4ee8 2768 assert(pcoinsTip->GetSproutAnchorAt(current_anchor, dummy_tree));
a8ac403d
SB
2769
2770 pindex = chainActive.Next(pindex);
2771 }
2772
ccb439c5
SB
2773 // TODO: #93; Select a root via some heuristic.
2774 final_anchor = tree.root();
a8ac403d 2775
8ea8ef98 2776 BOOST_FOREACH(boost::optional<SproutWitness>& wit, witnesses) {
2dc35992
SB
2777 if (wit) {
2778 assert(final_anchor == wit->root());
2779 }
1760b3cd 2780 }
a8ac403d
SB
2781}
2782
5b40d886
MF
2783/**
2784 * Scan the block chain (starting in pindexStart) for transactions
2785 * from or to us. If fUpdate is true, found transactions that already
2786 * exist in the wallet will be updated.
2787 */
e8ef3da7
WL
2788int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
2789{
2790 int ret = 0;
75b8953a 2791 int64_t nNow = GetTime();
11982d36 2792 const CChainParams& chainParams = Params();
e8ef3da7
WL
2793
2794 CBlockIndex* pindex = pindexStart;
cd10562c
S
2795
2796 std::vector<uint256> myTxHashes;
2797
e8ef3da7 2798 {
55a1db4f 2799 LOCK2(cs_main, cs_wallet);
39278369
CL
2800
2801 // no need to read and scan block, if block was created before
2802 // our wallet birthday (as adjusted for block time variability)
209377a7 2803 while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200)))
39278369
CL
2804 pindex = chainActive.Next(pindex);
2805
2806 ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
11982d36 2807 double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false);
86131275 2808 double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip(), false);
e8ef3da7
WL
2809 while (pindex)
2810 {
4b729ec5 2811 if (pindex->GetHeight() % 100 == 0 && dProgressTip - dProgressStart > 0.0)
11982d36 2812 ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
8da9dd07 2813
e8ef3da7 2814 CBlock block;
b8add6a4 2815 ReadBlockFromDisk(block, pindex,1);
e8ef3da7
WL
2816 BOOST_FOREACH(CTransaction& tx, block.vtx)
2817 {
cd10562c
S
2818 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
2819 myTxHashes.push_back(tx.GetHash());
e8ef3da7 2820 ret++;
cd10562c 2821 }
e8ef3da7 2822 }
b6961fc1 2823
4fc309f0
EOW
2824 SproutMerkleTree sproutTree;
2825 SaplingMerkleTree saplingTree;
b6961fc1
JG
2826 // This should never fail: we should always be able to get the tree
2827 // state on the path to the tip of our chain
f86ee1c2
EOW
2828 assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree));
2829 if (pindex->pprev) {
4b729ec5 2830 if (NetworkUpgradeActive(pindex->pprev->GetHeight(), Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
d9fe33b8
S
2831 assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree));
2832 }
f86ee1c2 2833 }
b6961fc1 2834 // Increment note witness caches
f0dcfceb 2835 ChainTip(pindex, &block, sproutTree, saplingTree, true);
b6961fc1 2836
4c6d41b8 2837 pindex = chainActive.Next(pindex);
75b8953a
B
2838 if (GetTime() >= nNow + 60) {
2839 nNow = GetTime();
4b729ec5 2840 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->GetHeight(), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
75b8953a 2841 }
e8ef3da7 2842 }
cd10562c
S
2843
2844 // After rescanning, persist Sapling note data that might have changed, e.g. nullifiers.
2845 // Do not flush the wallet here for performance reasons.
2846 CWalletDB walletdb(strWalletFile, "r+", false);
2847 for (auto hash : myTxHashes) {
2848 CWalletTx wtx = mapWallet[hash];
2849 if (!wtx.mapSaplingNoteData.empty()) {
2850 if (!wtx.WriteToDisk(&walletdb)) {
2851 LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString());
2852 }
2853 }
2854 }
2855
39278369 2856 ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
e8ef3da7
WL
2857 }
2858 return ret;
2859}
2860
2861void CWallet::ReacceptWalletTransactions()
2862{
7e6d23b1 2863 // If transactions aren't being broadcasted, don't let them into local mempool either
6f252627
WL
2864 if (!fBroadcastTransactions)
2865 return;
55a1db4f 2866 LOCK2(cs_main, cs_wallet);
e9c3215b 2867 std::map<int64_t, CWalletTx*> mapSorted;
2868
2869 // Sort pending wallet transactions based on their initial wallet insertion order
93a18a36 2870 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
e8ef3da7 2871 {
93a18a36
GA
2872 const uint256& wtxid = item.first;
2873 CWalletTx& wtx = item.second;
805344dc 2874 assert(wtx.GetHash() == wtxid);
e8ef3da7 2875
93a18a36
GA
2876 int nDepth = wtx.GetDepthInMainChain();
2877
e9c3215b 2878 if (!wtx.IsCoinBase() && nDepth < 0) {
2879 mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
e8ef3da7
WL
2880 }
2881 }
e9c3215b 2882
43260416 2883 std::vector<uint256> vwtxh;
2884
e9c3215b 2885 // Try to add wallet transactions to memory pool
2886 BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted)
2887 {
2888 CWalletTx& wtx = *(item.second);
2889
2890 LOCK(mempool.cs);
271326fa 2891 CValidationState state;
2892 // attempt to add them, but don't set any DOS level
085c3640 2893 if (!::AcceptToMemoryPool(mempool, state, wtx, false, NULL, true, 0))
2894 {
2895 int nDoS;
2896 bool invalid = state.IsInvalid(nDoS);
2897
2898 // log rejection and deletion
2899 // printf("ERROR reaccepting wallet transaction %s to mempool, reason: %s, DoS: %d\n", wtx.GetHash().ToString().c_str(), state.GetRejectReason().c_str(), nDoS);
2900
2901 if (!wtx.IsCoinBase() && invalid && nDoS > 0)
2902 {
d738023b 2903 LogPrintf("erasing transaction %s\n", wtx.GetHash().GetHex().c_str());
43260416 2904 vwtxh.push_back(wtx.GetHash());
085c3640 2905 }
2906 }
e9c3215b 2907 }
43260416 2908 for (auto hash : vwtxh)
2909 {
2910 EraseFromWallet(hash);
2911 }
e8ef3da7
WL
2912}
2913
0f5954c4 2914bool CWalletTx::RelayWalletTransaction()
e8ef3da7 2915{
7000ef1a 2916 if ( pwallet == 0 )
2917 {
2918 fprintf(stderr,"unexpected null pwallet in RelayWalletTransaction\n");
2919 return(false);
2920 }
6f252627 2921 assert(pwallet->GetBroadcastTransactions());
e8ef3da7
WL
2922 if (!IsCoinBase())
2923 {
bd070d8b 2924 if (GetDepthInMainChain() == 0)
2925 {
2926 // if tx is expired, dont relay
805344dc 2927 LogPrintf("Relaying wtx %s\n", GetHash().ToString());
d38da59b 2928 RelayTransaction((CTransaction)*this);
0f5954c4 2929 return true;
e8ef3da7
WL
2930 }
2931 }
0f5954c4 2932 return false;
e8ef3da7
WL
2933}
2934
3015e0bc 2935set<uint256> CWalletTx::GetConflicts() const
731b89b8
GA
2936{
2937 set<uint256> result;
2938 if (pwallet != NULL)
2939 {
805344dc 2940 uint256 myHash = GetHash();
3015e0bc 2941 result = pwallet->GetConflicts(myHash);
731b89b8
GA
2942 result.erase(myHash);
2943 }
2944 return result;
2945}
2946
bbacd882
CF
2947CAmount CWalletTx::GetDebit(const isminefilter& filter) const
2948{
2949 if (vin.empty())
2950 return 0;
2951
2952 CAmount debit = 0;
2953 if(filter & ISMINE_SPENDABLE)
2954 {
2955 if (fDebitCached)
2956 debit += nDebitCached;
2957 else
2958 {
2959 nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
2960 fDebitCached = true;
2961 debit += nDebitCached;
2962 }
2963 }
2964 if(filter & ISMINE_WATCH_ONLY)
2965 {
2966 if(fWatchDebitCached)
2967 debit += nWatchDebitCached;
2968 else
2969 {
2970 nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
2971 fWatchDebitCached = true;
2972 debit += nWatchDebitCached;
2973 }
2974 }
2975 return debit;
2976}
2977
2978CAmount CWalletTx::GetCredit(const isminefilter& filter) const
2979{
2980 // Must wait until coinbase is safely deep enough in the chain before valuing it
2981 if (IsCoinBase() && GetBlocksToMaturity() > 0)
2982 return 0;
2983
2984 int64_t credit = 0;
2985 if (filter & ISMINE_SPENDABLE)
2986 {
2987 // GetBalance can assume transactions in mapWallet won't change
2988 if (fCreditCached)
2989 credit += nCreditCached;
2990 else
2991 {
2992 nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
2993 fCreditCached = true;
2994 credit += nCreditCached;
2995 }
2996 }
2997 if (filter & ISMINE_WATCH_ONLY)
2998 {
2999 if (fWatchCreditCached)
3000 credit += nWatchCreditCached;
3001 else
3002 {
3003 nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
3004 fWatchCreditCached = true;
3005 credit += nWatchCreditCached;
3006 }
3007 }
3008 return credit;
3009}
3010
3011CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
3012{
3013 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
3014 {
3015 if (fUseCache && fImmatureCreditCached)
3016 return nImmatureCreditCached;
3017 nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
3018 fImmatureCreditCached = true;
3019 return nImmatureCreditCached;
3020 }
3021
3022 return 0;
3023}
3024
3025CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
3026{
3027 if (pwallet == 0)
3028 return 0;
3029
3030 // Must wait until coinbase is safely deep enough in the chain before valuing it
3031 if (IsCoinBase() && GetBlocksToMaturity() > 0)
3032 return 0;
3033
3034 if (fUseCache && fAvailableCreditCached)
3035 return nAvailableCreditCached;
3036
3037 CAmount nCredit = 0;
805344dc 3038 uint256 hashTx = GetHash();
bbacd882
CF
3039 for (unsigned int i = 0; i < vout.size(); i++)
3040 {
3041 if (!pwallet->IsSpent(hashTx, i))
3042 {
fab1429d 3043 nCredit += pwallet->GetCredit(*this, i, ISMINE_SPENDABLE);
bbacd882
CF
3044 if (!MoneyRange(nCredit))
3045 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
3046 }
3047 }
3048
3049 nAvailableCreditCached = nCredit;
3050 fAvailableCreditCached = true;
3051 return nCredit;
3052}
3053
3054CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
3055{
3056 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
3057 {
3058 if (fUseCache && fImmatureWatchCreditCached)
3059 return nImmatureWatchCreditCached;
3060 nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
3061 fImmatureWatchCreditCached = true;
3062 return nImmatureWatchCreditCached;
3063 }
3064
3065 return 0;
3066}
3067
3068CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
3069{
3070 if (pwallet == 0)
3071 return 0;
3072
3073 // Must wait until coinbase is safely deep enough in the chain before valuing it
3074 if (IsCoinBase() && GetBlocksToMaturity() > 0)
3075 return 0;
3076
3077 if (fUseCache && fAvailableWatchCreditCached)
3078 return nAvailableWatchCreditCached;
3079
3080 CAmount nCredit = 0;
3081 for (unsigned int i = 0; i < vout.size(); i++)
3082 {
805344dc 3083 if (!pwallet->IsSpent(GetHash(), i))
bbacd882 3084 {
fab1429d 3085 nCredit += pwallet->GetCredit(*this, i, ISMINE_WATCH_ONLY);
bbacd882
CF
3086 if (!MoneyRange(nCredit))
3087 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
3088 }
3089 }
3090
3091 nAvailableWatchCreditCached = nCredit;
3092 fAvailableWatchCreditCached = true;
3093 return nCredit;
3094}
3095
3096CAmount CWalletTx::GetChange() const
3097{
3098 if (fChangeCached)
3099 return nChangeCached;
3100 nChangeCached = pwallet->GetChange(*this);
3101 fChangeCached = true;
3102 return nChangeCached;
3103}
3104
3105bool CWalletTx::IsTrusted() const
3106{
3107 // Quick answer in most cases
75a4d512 3108 if (!CheckFinalTx(*this))
bbacd882
CF
3109 return false;
3110 int nDepth = GetDepthInMainChain();
3111 if (nDepth >= 1)
3112 return true;
3113 if (nDepth < 0)
3114 return false;
3115 if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
3116 return false;
3117
3118 // Trusted if all inputs are from us and are in the mempool:
3119 BOOST_FOREACH(const CTxIn& txin, vin)
3120 {
3121 // Transactions not sent by us: not trusted
3122 const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
3123 if (parent == NULL)
3124 return false;
3125 const CTxOut& parentOut = parent->vout[txin.prevout.n];
3126 if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
3127 return false;
3128 }
3129 return true;
3130}
3131
0f5954c4
GA
3132std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
3133{
3134 std::vector<uint256> result;
3135
3136 LOCK(cs_wallet);
3137 // Sort them in chronological order
3138 multimap<unsigned int, CWalletTx*> mapSorted;
bd070d8b 3139 uint32_t now = (uint32_t)time(NULL);
47ab0926 3140 std::vector<uint256> vwtxh;
0f5954c4
GA
3141 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
3142 {
3143 CWalletTx& wtx = item.second;
3144 // Don't rebroadcast if newer than nTime:
3145 if (wtx.nTimeReceived > nTime)
3146 continue;
3abeed2c 3147 if ( (wtx.nLockTime >= LOCKTIME_THRESHOLD && wtx.nLockTime < now-KOMODO_MAXMEMPOOLTIME) || wtx.hashBlock.IsNull() )
bd070d8b 3148 {
1aa576ad 3149 //LogPrintf("skip Relaying wtx %s nLockTime %u vs now.%u\n", wtx.GetHash().ToString(),(uint32_t)wtx.nLockTime,now);
d738023b 3150 //vwtxh.push_back(wtx.GetHash());
3abeed2c 3151 continue;
bd070d8b 3152 }
0f5954c4
GA
3153 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
3154 }
3155 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
3156 {
7000ef1a 3157 if ( item.second != 0 )
3158 {
3872e9cb 3159 CWalletTx &wtx = *item.second;
7000ef1a 3160 if (wtx.RelayWalletTransaction())
3161 result.push_back(wtx.GetHash());
3162 }
0f5954c4 3163 }
47ab0926 3164 for (auto hash : vwtxh)
3165 {
d738023b 3166 EraseFromWallets(hash);
47ab0926 3167 }
0f5954c4
GA
3168 return result;
3169}
3170
3171void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
e8ef3da7
WL
3172{
3173 // Do this infrequently and randomly to avoid giving away
3174 // that these are our transactions.
6f252627 3175 if (GetTime() < nNextResend || !fBroadcastTransactions)
e8ef3da7 3176 return;
203d1ae6
LD
3177 bool fFirst = (nNextResend == 0);
3178 nNextResend = GetTime() + GetRand(30 * 60);
e8ef3da7
WL
3179 if (fFirst)
3180 return;
3181
3182 // Only do it if there's been a new block since last time
0f5954c4 3183 if (nBestBlockTime < nLastResend)
e8ef3da7 3184 return;
203d1ae6 3185 nLastResend = GetTime();
e8ef3da7 3186
0f5954c4
GA
3187 // Rebroadcast unconfirmed txes older than 5 minutes before the last
3188 // block was found:
3189 std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60);
3190 if (!relayed.empty())
3191 LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
e8ef3da7
WL
3192}
3193
5b40d886 3194/** @} */ // end of mapWallet
e8ef3da7
WL
3195
3196
3197
3198
5b40d886
MF
3199/** @defgroup Actions
3200 *
3201 * @{
3202 */
e8ef3da7
WL
3203
3204
a372168e 3205CAmount CWallet::GetBalance() const
e8ef3da7 3206{
a372168e 3207 CAmount nTotal = 0;
e8ef3da7 3208 {
55a1db4f 3209 LOCK2(cs_main, cs_wallet);
e8ef3da7
WL
3210 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3211 {
3212 const CWalletTx* pcoin = &(*it).second;
0542619d 3213 if (pcoin->IsTrusted())
8fdb7e10 3214 nTotal += pcoin->GetAvailableCredit();
e8ef3da7
WL
3215 }
3216 }
3217
e8ef3da7
WL
3218 return nTotal;
3219}
3220
a372168e 3221CAmount CWallet::GetUnconfirmedBalance() const
df5ccbd2 3222{
a372168e 3223 CAmount nTotal = 0;
df5ccbd2 3224 {
55a1db4f 3225 LOCK2(cs_main, cs_wallet);
df5ccbd2
WL
3226 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3227 {
3228 const CWalletTx* pcoin = &(*it).second;
75a4d512 3229 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
8fdb7e10 3230 nTotal += pcoin->GetAvailableCredit();
3231 }
3232 }
3233 return nTotal;
3234}
3235
a372168e 3236CAmount CWallet::GetImmatureBalance() const
8fdb7e10 3237{
a372168e 3238 CAmount nTotal = 0;
8fdb7e10 3239 {
55a1db4f 3240 LOCK2(cs_main, cs_wallet);
8fdb7e10 3241 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3242 {
966a0e8c
PK
3243 const CWalletTx* pcoin = &(*it).second;
3244 nTotal += pcoin->GetImmatureCredit();
df5ccbd2
WL
3245 }
3246 }
3247 return nTotal;
3248}
e8ef3da7 3249
a372168e 3250CAmount CWallet::GetWatchOnlyBalance() const
ffd40da3 3251{
a372168e 3252 CAmount nTotal = 0;
ffd40da3 3253 {
39cc4922 3254 LOCK2(cs_main, cs_wallet);
ffd40da3
J
3255 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3256 {
3257 const CWalletTx* pcoin = &(*it).second;
3258 if (pcoin->IsTrusted())
3259 nTotal += pcoin->GetAvailableWatchOnlyCredit();
3260 }
3261 }
870da77d 3262
ffd40da3
J
3263 return nTotal;
3264}
3265
a372168e 3266CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
ffd40da3 3267{
a372168e 3268 CAmount nTotal = 0;
ffd40da3 3269 {
39cc4922 3270 LOCK2(cs_main, cs_wallet);
ffd40da3
J
3271 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3272 {
3273 const CWalletTx* pcoin = &(*it).second;
75a4d512 3274 if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
ffd40da3
J
3275 nTotal += pcoin->GetAvailableWatchOnlyCredit();
3276 }
3277 }
3278 return nTotal;
3279}
3280
a372168e 3281CAmount CWallet::GetImmatureWatchOnlyBalance() const
ffd40da3 3282{
a372168e 3283 CAmount nTotal = 0;
ffd40da3 3284 {
39cc4922 3285 LOCK2(cs_main, cs_wallet);
ffd40da3
J
3286 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3287 {
3288 const CWalletTx* pcoin = &(*it).second;
3289 nTotal += pcoin->GetImmatureWatchOnlyCredit();
3290 }
3291 }
3292 return nTotal;
3293}
3294
5b40d886
MF
3295/**
3296 * populate vCoins with vector of available COutputs.
3297 */
79383e0a 3298uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
c60397dd 3299uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
0ad6a463 3300
be4f847b 3301void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const
9b0369c7 3302{
5c439232 3303 uint64_t interest,*ptr;
9b0369c7
CM
3304 vCoins.clear();
3305
3306 {
ea3acaf3 3307 LOCK2(cs_main, cs_wallet);
9b0369c7
CM
3308 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3309 {
93a18a36 3310 const uint256& wtxid = it->first;
9b0369c7
CM
3311 const CWalletTx* pcoin = &(*it).second;
3312
75a4d512 3313 if (!CheckFinalTx(*pcoin))
a2709fad
GA
3314 continue;
3315
0542619d 3316 if (fOnlyConfirmed && !pcoin->IsTrusted())
9b0369c7
CM
3317 continue;
3318
2b1cda3b
S
3319 if (pcoin->IsCoinBase() && !fIncludeCoinBase)
3320 continue;
3321
9b0369c7
CM
3322 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
3323 continue;
3324
2b72d46f
GA
3325 int nDepth = pcoin->GetDepthInMainChain();
3326 if (nDepth < 0)
3327 continue;
53dce971 3328
fab1429d 3329 for (int i = 0; i < pcoin->vout.size(); i++)
0ad6a463 3330 {
ea340a14 3331 isminetype mine = IsMine(pcoin->vout[i]);
a3e192a3 3332 if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
219953ce 3333 !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) &&
6a86c24d 3334 (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
0ad6a463 3335 {
6ad13d7c 3336 if ( KOMODO_EXCHANGEWALLET == 0 )
0ad6a463 3337 {
6ad13d7c 3338 uint32_t locktime; int32_t txheight; CBlockIndex *tipindex;
4b729ec5 3339 if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->GetHeight() >= 60000 )
0ad6a463 3340 {
6ad13d7c 3341 if ( pcoin->vout[i].nValue >= 10*COIN )
9d92c93d 3342 {
86131275 3343 if ( (tipindex= chainActive.LastTip()) != 0 )
6ad13d7c 3344 {
4b729ec5 3345 komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue,(int32_t)tipindex->GetHeight());
79383e0a 3346 interest = komodo_interestnew(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime);
6ad13d7c 3347 } else interest = 0;
4b729ec5 3348 //interest = komodo_interestnew(chainActive.LastTip()->GetHeight()+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.LastTip()->nTime);
6ad13d7c 3349 if ( interest != 0 )
3350 {
3351 //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);
4b729ec5 3352 //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);
6ad13d7c 3353 //ptr = (uint64_t *)&pcoin->vout[i].nValue;
3354 //(*ptr) += interest;
3355 ptr = (uint64_t *)&pcoin->vout[i].interest;
3356 (*ptr) = interest;
3357 //pcoin->vout[i].nValue += interest;
3358 }
3359 else
3360 {
3361 ptr = (uint64_t *)&pcoin->vout[i].interest;
3362 (*ptr) = 0;
3363 }
e9e8044e 3364 }
258748f5 3365 else
3366 {
3367 ptr = (uint64_t *)&pcoin->vout[i].interest;
3368 (*ptr) = 0;
3369 }
0ad6a463 3370 }
258748f5 3371 else
3372 {
3373 ptr = (uint64_t *)&pcoin->vout[i].interest;
3374 (*ptr) = 0;
3375 }
3376 }
0ad6a463 3377 vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO));
3378 }
fdbb537d 3379 }
9b0369c7
CM
3380 }
3381 }
3382}
3383
0ad6a463 3384static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
831f59ce
CM
3385{
3386 vector<char> vfIncluded;
3387
3388 vfBest.assign(vValue.size(), true);
3389 nBest = nTotalLower;
3390
907a2aa4
GM
3391 seed_insecure_rand();
3392
831f59ce
CM
3393 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
3394 {
3395 vfIncluded.assign(vValue.size(), false);
a372168e 3396 CAmount nTotal = 0;
831f59ce
CM
3397 bool fReachedTarget = false;
3398 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
3399 {
3400 for (unsigned int i = 0; i < vValue.size(); i++)
3401 {
907a2aa4
GM
3402 //The solver here uses a randomized algorithm,
3403 //the randomness serves no real security purpose but is just
3404 //needed to prevent degenerate behavior and it is important
5b40d886 3405 //that the rng is fast. We do not use a constant random sequence,
907a2aa4
GM
3406 //because there may be some privacy improvement by making
3407 //the selection random.
3408 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
831f59ce
CM
3409 {
3410 nTotal += vValue[i].first;
3411 vfIncluded[i] = true;
3412 if (nTotal >= nTargetValue)
3413 {
3414 fReachedTarget = true;
3415 if (nTotal < nBest)
3416 {
3417 nBest = nTotal;
3418 vfBest = vfIncluded;
3419 }
3420 nTotal -= vValue[i].first;
3421 vfIncluded[i] = false;
3422 }
3423 }
3424 }
3425 }
3426 }
3427}
3428
79383e0a 3429bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
e8ef3da7 3430{
79383e0a 3431 int32_t count = 0; //uint64_t lowest_interest = 0;
e8ef3da7 3432 setCoinsRet.clear();
79383e0a 3433 //memset(interests,0,sizeof(interests));
e8ef3da7 3434 nValueRet = 0;
e8ef3da7 3435 // List of values less than target
a372168e
MF
3436 pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
3437 coinLowestLarger.first = std::numeric_limits<CAmount>::max();
e8ef3da7 3438 coinLowestLarger.second.first = NULL;
a372168e
MF
3439 vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue;
3440 CAmount nTotalLower = 0;
e8ef3da7 3441
e333ab56
CM
3442 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
3443
c8988460 3444 BOOST_FOREACH(const COutput &output, vCoins)
e8ef3da7 3445 {
c8988460
PW
3446 if (!output.fSpendable)
3447 continue;
3448
9b0369c7 3449 const CWalletTx *pcoin = output.tx;
e8ef3da7 3450
a3e192a3 3451 if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
9b0369c7 3452 continue;
e8ef3da7 3453
9b0369c7 3454 int i = output.i;
a372168e 3455 CAmount n = pcoin->vout[i].nValue;
e8ef3da7 3456
a372168e 3457 pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
e8ef3da7 3458
9b0369c7
CM
3459 if (n == nTargetValue)
3460 {
3461 setCoinsRet.insert(coin.second);
3462 nValueRet += coin.first;
79383e0a 3463 //if ( KOMODO_EXCHANGEWALLET == 0 )
3464 // *interestp += pcoin->vout[i].interest;
9b0369c7
CM
3465 return true;
3466 }
3467 else if (n < nTargetValue + CENT)
3468 {
3469 vValue.push_back(coin);
3470 nTotalLower += n;
79383e0a 3471 //if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) )
3472 //{
9067057a 3473 //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN);
79383e0a 3474 //interests[count++] = pcoin->vout[i].interest;
3475 //}
3476 if ( nTotalLower > 4*nTargetValue + CENT )
92c2aa6b 3477 {
eaba9a27 3478 //fprintf(stderr,"why bother with all the utxo if we have double what is needed?\n");
92c2aa6b 3479 break;
3480 }
9b0369c7
CM
3481 }
3482 else if (n < coinLowestLarger.first)
3483 {
3484 coinLowestLarger = coin;
79383e0a 3485 //if ( KOMODO_EXCHANGEWALLET == 0 )
3486 // lowest_interest = pcoin->vout[i].interest;
e8ef3da7
WL
3487 }
3488 }
3489
831f59ce 3490 if (nTotalLower == nTargetValue)
e8ef3da7 3491 {
c376ac35 3492 for (unsigned int i = 0; i < vValue.size(); ++i)
e8ef3da7
WL
3493 {
3494 setCoinsRet.insert(vValue[i].second);
3495 nValueRet += vValue[i].first;
79383e0a 3496 //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
3497 // *interestp += interests[i];
e8ef3da7
WL
3498 }
3499 return true;
3500 }
3501
831f59ce 3502 if (nTotalLower < nTargetValue)
e8ef3da7
WL
3503 {
3504 if (coinLowestLarger.second.first == NULL)
3505 return false;
3506 setCoinsRet.insert(coinLowestLarger.second);
3507 nValueRet += coinLowestLarger.first;
79383e0a 3508 //if ( KOMODO_EXCHANGEWALLET == 0 )
3509 // *interestp += lowest_interest;
e8ef3da7
WL
3510 return true;
3511 }
3512
e8ef3da7 3513 // Solve subset sum by stochastic approximation
d650f96d 3514 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
831f59ce 3515 vector<char> vfBest;
a372168e 3516 CAmount nBest;
e8ef3da7 3517
831f59ce
CM
3518 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
3519 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
3520 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
e8ef3da7 3521
831f59ce
CM
3522 // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
3523 // or the next bigger coin is closer), return the bigger coin
3524 if (coinLowestLarger.second.first &&
3525 ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
e8ef3da7
WL
3526 {
3527 setCoinsRet.insert(coinLowestLarger.second);
3528 nValueRet += coinLowestLarger.first;
79383e0a 3529 //if ( KOMODO_EXCHANGEWALLET == 0 )
3530 // *interestp += lowest_interest;
e8ef3da7
WL
3531 }
3532 else {
c376ac35 3533 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7
WL
3534 if (vfBest[i])
3535 {
3536 setCoinsRet.insert(vValue[i].second);
3537 nValueRet += vValue[i].first;
79383e0a 3538 //if ( KOMODO_EXCHANGEWALLET == 0 && i < count )
3539 // *interestp += interests[i];
e8ef3da7
WL
3540 }
3541
faaeae1e 3542 LogPrint("selectcoins", "SelectCoins() best subset: ");
c376ac35 3543 for (unsigned int i = 0; i < vValue.size(); i++)
e8ef3da7 3544 if (vfBest[i])
4f0f864d 3545 LogPrint("selectcoins", "%s", FormatMoney(vValue[i].first));
7d9d134b 3546 LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
e8ef3da7
WL
3547 }
3548
3549 return true;
3550}
3551
79383e0a 3552bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const
e8ef3da7 3553{
2b1cda3b 3554 // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
79383e0a 3555 uint64_t tmp; int32_t retval;
3556 //if ( interestp == 0 )
3557 //{
3558 // interestp = &tmp;
3559 // *interestp = 0;
3560 //}
2b1cda3b
S
3561 vector<COutput> vCoinsNoCoinbase, vCoinsWithCoinbase;
3562 AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false);
3563 AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true);
3564 fOnlyCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
3565
3566 // If coinbase utxos can only be sent to zaddrs, exclude any coinbase utxos from coin selection.
3567 bool fProtectCoinbase = Params().GetConsensus().fCoinbaseMustBeProtected;
3568 vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
3569
3570 // Output parameter fNeedCoinbaseCoinsRet is set to true if coinbase utxos need to be spent to meet target amount
3571 if (fProtectCoinbase && vCoinsWithCoinbase.size() > vCoinsNoCoinbase.size()) {
3572 CAmount value = 0;
3573 for (const COutput& out : vCoinsNoCoinbase) {
3574 if (!out.fSpendable) {
3575 continue;
3576 }
3577 value += out.tx->vout[out.i].nValue;
f87150f4 3578 if ( KOMODO_EXCHANGEWALLET == 0 )
3579 value += out.tx->vout[out.i].interest;
2b1cda3b
S
3580 }
3581 if (value <= nTargetValue) {
3582 CAmount valueWithCoinbase = 0;
3583 for (const COutput& out : vCoinsWithCoinbase) {
3584 if (!out.fSpendable) {
3585 continue;
3586 }
3587 valueWithCoinbase += out.tx->vout[out.i].nValue;
f87150f4 3588 if ( KOMODO_EXCHANGEWALLET == 0 )
3589 valueWithCoinbase += out.tx->vout[out.i].interest;
2b1cda3b
S
3590 }
3591 fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
3592 }
3593 }
6a86c24d 3594 // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
aa30f655 3595 if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
6a86c24d
CL
3596 {
3597 BOOST_FOREACH(const COutput& out, vCoins)
3598 {
aa30f655
MC
3599 if (!out.fSpendable)
3600 continue;
6a86c24d 3601 nValueRet += out.tx->vout[out.i].nValue;
79383e0a 3602 //if ( KOMODO_EXCHANGEWALLET == 0 )
3603 // *interestp += out.tx->vout[out.i].interest;
6a86c24d
CL
3604 setCoinsRet.insert(make_pair(out.tx, out.i));
3605 }
3606 return (nValueRet >= nTargetValue);
3607 }
aa30f655
MC
3608 // calculate value from preset inputs and store them
3609 set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
3610 CAmount nValueFromPresetInputs = 0;
3611
3612 std::vector<COutPoint> vPresetInputs;
3613 if (coinControl)
3614 coinControl->ListSelected(vPresetInputs);
3615 BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
3616 {
3617 map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
3618 if (it != mapWallet.end())
3619 {
3620 const CWalletTx* pcoin = &it->second;
3621 // Clearly invalid input, fail
3622 if (pcoin->vout.size() <= outpoint.n)
3623 return false;
3624 nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue;
945f015d 3625 if ( KOMODO_EXCHANGEWALLET == 0 )
3626 nValueFromPresetInputs += pcoin->vout[outpoint.n].interest;
aa30f655
MC
3627 setPresetCoins.insert(make_pair(pcoin, outpoint.n));
3628 } else
3629 return false; // TODO: Allow non-wallet inputs
3630 }
3631
3632 // remove preset inputs from vCoins
3633 for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
3634 {
3635 if (setPresetCoins.count(make_pair(it->tx, it->i)))
3636 it = vCoins.erase(it);
3637 else
3638 ++it;
3639 }
945f015d 3640 retval = false;
3641 if ( nTargetValue <= nValueFromPresetInputs )
3642 retval = true;
79383e0a 3643 else if ( SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) != 0 )
945f015d 3644 retval = true;
79383e0a 3645 else if ( SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) != 0 )
945f015d 3646 retval = true;
79383e0a 3647 else if ( bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet) != 0 )
945f015d 3648 retval = true;
aa30f655
MC
3649 // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
3650 setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
aa30f655
MC
3651 // add preset inputs to the total value selected
3652 nValueRet += nValueFromPresetInputs;
945f015d 3653 return retval;
e8ef3da7
WL
3654}
3655
aa30f655
MC
3656bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason)
3657{
3658 vector<CRecipient> vecSend;
3659
3660 // Turn the txout set into a CRecipient vector
3661 BOOST_FOREACH(const CTxOut& txOut, tx.vout)
3662 {
3663 CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false};
3664 vecSend.push_back(recipient);
3665 }
3666
3667 CCoinControl coinControl;
3668 coinControl.fAllowOtherInputs = true;
3669 BOOST_FOREACH(const CTxIn& txin, tx.vin)
3670 coinControl.Select(txin.prevout);
3671
3672 CReserveKey reservekey(this);
3673 CWalletTx wtx;
efb7662d 3674
aa30f655
MC
3675 if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
3676 return false;
3677
3678 if (nChangePosRet != -1)
3679 tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
3680
3681 // Add new txins (keeping original txin scriptSig/order)
3682 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
3683 {
3684 bool found = false;
3685 BOOST_FOREACH(const CTxIn& origTxIn, tx.vin)
3686 {
3687 if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
3688 {
3689 found = true;
3690 break;
3691 }
3692 }
3693 if (!found)
3694 tx.vin.push_back(txin);
3695 }
3696
3697 return true;
e8ef3da7
WL
3698}
3699
aa30f655
MC
3700bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
3701 int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
e8ef3da7 3702{
79383e0a 3703 uint64_t interest2 = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0;
292623ad 3704 BOOST_FOREACH (const CRecipient& recipient, vecSend)
e8ef3da7 3705 {
292623ad 3706 if (nValue < 0 || recipient.nAmount < 0)
1f00f4e9
GA
3707 {
3708 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 3709 return false;
1f00f4e9 3710 }
292623ad
CL
3711 nValue += recipient.nAmount;
3712
3713 if (recipient.fSubtractFeeFromAmount)
3714 nSubtractFeeFromAmount++;
e8ef3da7
WL
3715 }
3716 if (vecSend.empty() || nValue < 0)
1f00f4e9
GA
3717 {
3718 strFailReason = _("Transaction amounts must be positive");
e8ef3da7 3719 return false;
1f00f4e9 3720 }
e8ef3da7 3721
b33d1f5e 3722 wtxNew.fTimeReceivedIsTxTime = true;
4c6e2295 3723 wtxNew.BindWallet(this);
9bb37bf0 3724 int nextBlockHeight = chainActive.Height() + 1;
072099d7 3725 CMutableTransaction txNew = CreateNewContextualCMutableTransaction(
9000990c 3726 Params().GetConsensus(), nextBlockHeight);
86131275 3727 txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now
e8ef3da7 3728
9bb37bf0 3729 // Activates after Overwinter network upgrade
9bb37bf0 3730 if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
fa70084c 3731 if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){
9bb37bf0 3732 strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD.");
7b92f27e 3733 return false;
9bb37bf0 3734 }
e19d8b3d 3735 }
15ec5525 3736
25fee350 3737 unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
15ec5525
JG
3738 if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
3739 max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING;
3740 }
efb7662d 3741
ba7fcc8d
PT
3742 // Discourage fee sniping.
3743 //
3744 // However because of a off-by-one-error in previous versions we need to
3745 // neuter it by setting nLockTime to at least one less than nBestHeight.
3746 // Secondly currently propagation of transactions created for block heights
3747 // corresponding to blocks that were just mined may be iffy - transactions
3748 // aren't re-accepted into the mempool - we additionally neuter the code by
3749 // going ten blocks back. Doesn't yet do anything for sniping, but does act
3750 // to shake out wallet bugs like not showing nLockTime'd transactions at
3751 // all.
3752 txNew.nLockTime = std::max(0, chainActive.Height() - 10);
3753
3754 // Secondly occasionally randomly pick a nLockTime even further back, so
3755 // that transactions that are delayed after signing for whatever reason,
3756 // e.g. high-latency mix networks and some CoinJoin implementations, have
3757 // better privacy.
3758 if (GetRandInt(10) == 0)
3759 txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
3760
3761 assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
3762 assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
3763
e8ef3da7 3764 {
f8dcd5ca 3765 LOCK2(cs_main, cs_wallet);
e8ef3da7 3766 {
c1c9d5b4 3767 nFeeRet = 0;
050d2e95 3768 while (true)
e8ef3da7 3769 {
f19ffc34 3770 //interest = 0;
4949004d
PW
3771 txNew.vin.clear();
3772 txNew.vout.clear();
e8ef3da7 3773 wtxNew.fFromMe = true;
292623ad
CL
3774 nChangePosRet = -1;
3775 bool fFirst = true;
e8ef3da7 3776
292623ad
CL
3777 CAmount nTotalValue = nValue;
3778 if (nSubtractFeeFromAmount == 0)
3779 nTotalValue += nFeeRet;
e8ef3da7
WL
3780 double dPriority = 0;
3781 // vouts to the payees
292623ad 3782 BOOST_FOREACH (const CRecipient& recipient, vecSend)
8de9bb53 3783 {
292623ad
CL
3784 CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
3785
3786 if (recipient.fSubtractFeeFromAmount)
3787 {
3788 txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
3789
3790 if (fFirst) // first receiver pays the remainder not divisible by output count
3791 {
3792 fFirst = false;
3793 txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
3794 }
3795 }
3796
13fc83c7 3797 if (txout.IsDust(::minRelayTxFee))
1f00f4e9 3798 {
292623ad
CL
3799 if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
3800 {
3801 if (txout.nValue < 0)
3802 strFailReason = _("The transaction amount is too small to pay the fee");
3803 else
3804 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
3805 }
3806 else
3807 strFailReason = _("Transaction amount too small");
8de9bb53 3808 return false;
1f00f4e9 3809 }
4949004d 3810 txNew.vout.push_back(txout);
8de9bb53 3811 }
e8ef3da7
WL
3812
3813 // Choose coins to use
3814 set<pair<const CWalletTx*,unsigned int> > setCoins;
a372168e 3815 CAmount nValueIn = 0;
2b1cda3b
S
3816 bool fOnlyCoinbaseCoins = false;
3817 bool fNeedCoinbaseCoins = false;
9152feb5 3818 interest2 = 0;
79383e0a 3819 if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl))
1f00f4e9 3820 {
2b1cda3b
S
3821 if (fOnlyCoinbaseCoins && Params().GetConsensus().fCoinbaseMustBeProtected) {
3822 strFailReason = _("Coinbase funds can only be sent to a zaddr");
3823 } else if (fNeedCoinbaseCoins) {
3824 strFailReason = _("Insufficient funds, coinbase funds can only be spent after they have been sent to a zaddr");
3825 } else {
3826 strFailReason = _("Insufficient funds");
3827 }
e8ef3da7 3828 return false;
1f00f4e9 3829 }
e8ef3da7
WL
3830 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
3831 {
a372168e 3832 CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
2d9b0b7f 3833 //The coin age after the next block (depth+1) is used instead of the current,
d7836552
GM
3834 //reflecting an assumption the user would accept a bit more delay for
3835 //a chance at a free transaction.
2d9b0b7f 3836 //But mempool inputs might still be in the mempool, so their age stays 0
38dfbe15 3837 //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN);
d1f29a9d 3838 if ( KOMODO_EXCHANGEWALLET == 0 && ASSETCHAINS_SYMBOL[0] == 0 )
608252ed 3839 {
6ad13d7c 3840 interest2 += pcoin.first->vout[pcoin.second].interest;
d1f29a9d 3841 //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN);
85cb030e 3842 }
2d9b0b7f
AM
3843 int age = pcoin.first->GetDepthInMainChain();
3844 if (age != 0)
3845 age += 1;
3846 dPriority += (double)nCredit * age;
e8ef3da7 3847 }
79383e0a 3848 //if ( KOMODO_EXCHANGEWALLET != 0 )
3849 //{
2626c7e3 3850 //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN);
79383e0a 3851 //interest = 0; // interest2 also
3852 //}
1bc74c28 3853 if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 )
3854 {
817ad14d 3855 CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG;
3856 CTxOut newTxOut(interest2,scriptDonation);
719aa8b1 3857 int32_t nDonationPosRet = txNew.vout.size() - 1; // dont change first or last
3858 vector<CTxOut>::iterator position = txNew.vout.begin()+nDonationPosRet;
817ad14d 3859 txNew.vout.insert(position, newTxOut);
1bc74c28 3860 interest2 = 0;
3861 }
608252ed 3862 CAmount nChange = (nValueIn - nValue + interest2);
4ea19a87 3863//fprintf(stderr,"wallet change %.8f (%.8f - %.8f) interest2 %.8f total %.8f\n",(double)nChange/COIN,(double)nValueIn/COIN,(double)nValue/COIN,(double)interest2/COIN,(double)nTotalValue/COIN);
292623ad
CL
3864 if (nSubtractFeeFromAmount == 0)
3865 nChange -= nFeeRet;
a7dd11c6
PW
3866
3867 if (nChange > 0)
e8ef3da7 3868 {
bf798734
GA
3869 // Fill a vout to ourself
3870 // TODO: pass in scriptChange instead of reservekey so
3871 // change transaction isn't always pay-to-bitcoin-address
e8ef3da7 3872 CScript scriptChange;
6a86c24d
CL
3873
3874 // coin control: send change to custom address
3875 if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
0be990ba 3876 scriptChange = GetScriptForDestination(coinControl->destChange);
6a86c24d
CL
3877
3878 // no coin control: send change to newly generated address
3879 else
3880 {
3881 // Note: We use a new key here to keep it from being obvious which side is the change.
3882 // The drawback is that by not reusing a previous key, the change may be lost if a
3883 // backup is restored, if the backup doesn't have the new private key for the change.
3884 // If we reused the old key, it would be possible to add code to look for and
3885 // rediscover unknown transactions that were written with keys of ours to recover
3886 // post-backup change.
3887
3888 // Reserve a new key pair from key pool
3889 CPubKey vchPubKey;
3ec03ada 3890 extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY;
3891 if ( USE_EXTERNAL_PUBKEY == 0 )
3892 {
3ec03ada 3893 bool ret;
3894 ret = reservekey.GetReservedKey(vchPubKey);
3895 assert(ret); // should never fail, as we just unlocked
3896 scriptChange = GetScriptForDestination(vchPubKey.GetID());
3897 }
3898 else
3899 {
18c6cfce 3900 //fprintf(stderr,"use notary pubkey\n");
3ec03ada 3901 scriptChange = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
3902 }
6a86c24d 3903 }
e8ef3da7 3904
8de9bb53
GA
3905 CTxOut newTxOut(nChange, scriptChange);
3906
292623ad
CL
3907 // We do not move dust-change to fees, because the sender would end up paying more than requested.
3908 // This would be against the purpose of the all-inclusive feature.
3909 // So instead we raise the change and deduct from the recipient.
3910 if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee))
3911 {
3912 CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue;
3913 newTxOut.nValue += nDust; // raise change until no more dust
3914 for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
3915 {
3916 if (vecSend[i].fSubtractFeeFromAmount)
3917 {
3918 txNew.vout[i].nValue -= nDust;
3919 if (txNew.vout[i].IsDust(::minRelayTxFee))
3920 {
3921 strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
3922 return false;
3923 }
3924 break;
3925 }
3926 }
3927 }
3928
8de9bb53
GA
3929 // Never create dust outputs; if we would, just
3930 // add the dust to the fee.
13fc83c7 3931 if (newTxOut.IsDust(::minRelayTxFee))
8de9bb53
GA
3932 {
3933 nFeeRet += nChange;
3934 reservekey.ReturnKey();
3935 }
3936 else
3937 {
429dabb5 3938 nChangePosRet = txNew.vout.size() - 1; // dont change first or last
292623ad 3939 vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
4949004d 3940 txNew.vout.insert(position, newTxOut);
8de9bb53 3941 }
f38345e9 3942 } else reservekey.ReturnKey();
e8ef3da7
WL
3943
3944 // Fill vin
ba7fcc8d
PT
3945 //
3946 // Note how the sequence number is set to max()-1 so that the
3947 // nLockTime set above actually works.
e8ef3da7 3948 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
805344dc 3949 txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
ba7fcc8d 3950 std::numeric_limits<unsigned int>::max()-1));
e8ef3da7 3951
9e84b5aa
S
3952 // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
3953 size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
31afbcc5
JG
3954 {
3955 LOCK(cs_main);
3956 if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
3957 limit = 0;
3958 }
3959 }
9e84b5aa
S
3960 if (limit > 0) {
3961 size_t n = txNew.vin.size();
3962 if (n > limit) {
3963 strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
3964 return false;
3965 }
3966 }
3967
be126699
JG
3968 // Grab the current consensus branch ID
3969 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
3970
e8ef3da7
WL
3971 // Sign
3972 int nIn = 0;
aa30f655 3973 CTransaction txNewConst(txNew);
e8ef3da7 3974 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
aa30f655
MC
3975 {
3976 bool signSuccess;
3977 const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
157a5d0d 3978 SignatureData sigdata;
aa30f655 3979 if (sign)
be126699 3980 signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
aa30f655 3981 else
be126699 3982 signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
aa30f655
MC
3983
3984 if (!signSuccess)
1f00f4e9
GA
3985 {
3986 strFailReason = _("Signing transaction failed");
e8ef3da7 3987 return false;
157a5d0d
PW
3988 } else {
3989 UpdateTransaction(txNew, nIn, sigdata);
1f00f4e9 3990 }
157a5d0d 3991
aa30f655
MC
3992 nIn++;
3993 }
3994
3995 unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
3996
3997 // Remove scriptSigs if we used dummy signatures for fee calculation
3998 if (!sign) {
3999 BOOST_FOREACH (CTxIn& vin, txNew.vin)
4000 vin.scriptSig = CScript();
4001 }
e8ef3da7 4002
4949004d
PW
4003 // Embed the constructed transaction data in wtxNew.
4004 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
4005
e8ef3da7 4006 // Limit size
15ec5525 4007 if (nBytes >= max_tx_size)
1f00f4e9
GA
4008 {
4009 strFailReason = _("Transaction too large");
e8ef3da7 4010 return false;
1f00f4e9 4011 }
aa30f655 4012
4d707d51 4013 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
e8ef3da7 4014
aa279d61
GM
4015 // Can we complete this as a free transaction?
4016 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
4017 {
4018 // Not enough fee: enough priority?
4019 double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
4020 // Not enough mempool history to estimate: use hard-coded AllowFree.
4021 if (dPriorityNeeded <= 0 && AllowFree(dPriority))
4022 break;
4023
4024 // Small enough, and priority high enough, to send for free
4025 if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
4026 break;
4027 }
b33d1f5e 4028
1e3fdfaa 4029 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
4030 if ( nFeeNeeded < 5000 )
4031 nFeeNeeded = 5000;
b33d1f5e 4032
aa279d61
GM
4033 // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
4034 // because we must be at the maximum allowed fee.
4035 if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
e8ef3da7 4036 {
aa279d61
GM
4037 strFailReason = _("Transaction too large for fee policy");
4038 return false;
e8ef3da7
WL
4039 }
4040
aa279d61
GM
4041 if (nFeeRet >= nFeeNeeded)
4042 break; // Done, enough fee included.
b33d1f5e
GA
4043
4044 // Include more fee and try again.
4045 nFeeRet = nFeeNeeded;
4046 continue;
e8ef3da7
WL
4047 }
4048 }
4049 }
e8ef3da7 4050
292623ad 4051 return true;
e8ef3da7
WL
4052}
4053
5b40d886
MF
4054/**
4055 * Call after CreateTransaction unless you want to abort
4056 */
e8ef3da7
WL
4057bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
4058{
e8ef3da7 4059 {
f8dcd5ca 4060 LOCK2(cs_main, cs_wallet);
7d9d134b 4061 LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
e8ef3da7
WL
4062 {
4063 // This is only to keep the database open to defeat the auto-flush for the
4064 // duration of this scope. This is the only place where this optimization
4065 // maybe makes sense; please don't do it anywhere else.
44bc988e 4066 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
e8ef3da7
WL
4067
4068 // Take key pair from key pool so it won't be used again
4069 reservekey.KeepKey();
4070
4071 // Add tx to wallet, because if it has change it's also ours,
4072 // otherwise just for transaction history.
44bc988e 4073 AddToWallet(wtxNew, false, pwalletdb);
e8ef3da7 4074
93a18a36 4075 // Notify that old coins are spent
e8ef3da7
WL
4076 set<CWalletTx*> setCoins;
4077 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
4078 {
4079 CWalletTx &coin = mapWallet[txin.prevout.hash];
4c6e2295 4080 coin.BindWallet(this);
805344dc 4081 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
e8ef3da7
WL
4082 }
4083
4084 if (fFileBacked)
4085 delete pwalletdb;
4086 }
4087
4088 // Track how many getdata requests our transaction gets
805344dc 4089 mapRequestCount[wtxNew.GetHash()] = 0;
e8ef3da7 4090
6f252627 4091 if (fBroadcastTransactions)
e8ef3da7 4092 {
6f252627
WL
4093 // Broadcast
4094 if (!wtxNew.AcceptToMemoryPool(false))
4095 {
68c266b2 4096 fprintf(stderr,"commit failed\n");
83a426bc 4097 // This must not fail. The transaction has already been signed and recorded.
7ff9d122 4098 LogPrintf("CommitTransaction(): Error: Transaction not valid\n");
6f252627
WL
4099 return false;
4100 }
4101 wtxNew.RelayWalletTransaction();
e8ef3da7 4102 }
e8ef3da7 4103 }
e8ef3da7
WL
4104 return true;
4105}
4106
a372168e 4107CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
b33d1f5e
GA
4108{
4109 // payTxFee is user-set "I want to pay this much"
a372168e 4110 CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
c1c9d5b4
CL
4111 // user selected total at least (default=true)
4112 if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK())
4113 nFeeNeeded = payTxFee.GetFeePerK();
b33d1f5e
GA
4114 // User didn't set: use -txconfirmtarget to estimate...
4115 if (nFeeNeeded == 0)
4116 nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
4117 // ... unless we don't have enough mempool data, in which case fall
4118 // back to a hard-coded fee
4119 if (nFeeNeeded == 0)
13fc83c7 4120 nFeeNeeded = minTxFee.GetFee(nTxBytes);
aa279d61
GM
4121 // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
4122 if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
4123 nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
4124 // But always obey the maximum
4125 if (nFeeNeeded > maxTxFee)
4126 nFeeNeeded = maxTxFee;
b33d1f5e
GA
4127 return nFeeNeeded;
4128}
4129
e8ef3da7 4130
cf53fd7c 4131void komodo_prefetch(FILE *fp);
e8ef3da7 4132
eed1785f 4133DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
e8ef3da7
WL
4134{
4135 if (!fFileBacked)
4f76be1d 4136 return DB_LOAD_OK;
e8ef3da7 4137 fFirstRunRet = false;
e86c03cf 4138 if ( 0 ) // doesnt help
cf53fd7c 4139 {
e86c03cf 4140 fprintf(stderr,"loading wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
cf53fd7c 4141 FILE *fp;
4142 if ( (fp= fopen(strWalletFile.c_str(),"rb")) != 0 )
4143 {
4144 komodo_prefetch(fp);
4145 fclose(fp);
4146 }
4147 }
e86c03cf 4148 //fprintf(stderr,"prefetched wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
eed1785f 4149 DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
e86c03cf 4150 //fprintf(stderr,"loaded wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL));
d764d916 4151 if (nLoadWalletRet == DB_NEED_REWRITE)
9e9869d0 4152 {
d764d916
GA
4153 if (CDB::Rewrite(strWalletFile, "\x04pool"))
4154 {
012ca1c9 4155 LOCK(cs_wallet);
d764d916
GA
4156 setKeyPool.clear();
4157 // Note: can't top-up keypool here, because wallet is locked.
4158 // User will be prompted to unlock wallet the next operation
c6de7c35 4159 // that requires a new key.
d764d916 4160 }
9e9869d0
PW
4161 }
4162
7ec55267
MC
4163 if (nLoadWalletRet != DB_LOAD_OK)
4164 return nLoadWalletRet;
fd61d6f5 4165 fFirstRunRet = !vchDefaultKey.IsValid();
e8ef3da7 4166
39278369
CL
4167 uiInterface.LoadWallet(this);
4168
116df55e 4169 return DB_LOAD_OK;
e8ef3da7
WL
4170}
4171
ae3d0aba 4172
77cbd462 4173DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
518f3bda
JG
4174{
4175 if (!fFileBacked)
4176 return DB_LOAD_OK;
77cbd462 4177 DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx);
518f3bda
JG
4178 if (nZapWalletTxRet == DB_NEED_REWRITE)
4179 {
4180 if (CDB::Rewrite(strWalletFile, "\x04pool"))
4181 {
4182 LOCK(cs_wallet);
4183 setKeyPool.clear();
4184 // Note: can't top-up keypool here, because wallet is locked.
4185 // User will be prompted to unlock wallet the next operation
5b40d886 4186 // that requires a new key.
518f3bda
JG
4187 }
4188 }
4189
4190 if (nZapWalletTxRet != DB_LOAD_OK)
4191 return nZapWalletTxRet;
4192
4193 return DB_LOAD_OK;
4194}
4195
4196
a41d5fe0 4197bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
ae3d0aba 4198{
ca4cf5cf
GA
4199 bool fUpdated = false;
4200 {
4201 LOCK(cs_wallet); // mapAddressBook
4202 std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
4203 fUpdated = mi != mapAddressBook.end();
4204 mapAddressBook[address].name = strName;
4205 if (!strPurpose.empty()) /* update purpose only if requested */
4206 mapAddressBook[address].purpose = strPurpose;
4207 }
8d657a65 4208 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
ca4cf5cf 4209 strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
ae3d0aba
WL
4210 if (!fFileBacked)
4211 return false;
07444da1 4212 if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose))
a41d5fe0 4213 return false;
07444da1 4214 return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName);
ae3d0aba
WL
4215}
4216
a41d5fe0 4217bool CWallet::DelAddressBook(const CTxDestination& address)
ae3d0aba 4218{
b10e1470 4219 {
ca4cf5cf
GA
4220 LOCK(cs_wallet); // mapAddressBook
4221
4222 if(fFileBacked)
b10e1470 4223 {
ca4cf5cf 4224 // Delete destdata tuples associated with address
07444da1 4225 std::string strAddress = EncodeDestination(address);
ca4cf5cf
GA
4226 BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
4227 {
4228 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
4229 }
b10e1470 4230 }
ca4cf5cf 4231 mapAddressBook.erase(address);
b10e1470
WL
4232 }
4233
8d657a65 4234 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
ca4cf5cf 4235
ae3d0aba
WL
4236 if (!fFileBacked)
4237 return false;
07444da1
PW
4238 CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address));
4239 return CWalletDB(strWalletFile).EraseName(EncodeDestination(address));
ae3d0aba
WL
4240}
4241
fd61d6f5 4242bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
ae3d0aba
WL
4243{
4244 if (fFileBacked)
4245 {
4246 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
4247 return false;
4248 }
4249 vchDefaultKey = vchPubKey;
4250 return true;
4251}
4252
5b40d886
MF
4253/**
4254 * Mark old keypool keys as used,
efb7662d 4255 * and generate all new keys
5b40d886 4256 */
37971fcc
GA
4257bool CWallet::NewKeyPool()
4258{
37971fcc 4259 {
f8dcd5ca 4260 LOCK(cs_wallet);
37971fcc 4261 CWalletDB walletdb(strWalletFile);
51ed9ec9 4262 BOOST_FOREACH(int64_t nIndex, setKeyPool)
37971fcc
GA
4263 walletdb.ErasePool(nIndex);
4264 setKeyPool.clear();
4265
4266 if (IsLocked())
4267 return false;
4268
51ed9ec9 4269 int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
37971fcc
GA
4270 for (int i = 0; i < nKeys; i++)
4271 {
51ed9ec9 4272 int64_t nIndex = i+1;
37971fcc
GA
4273 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
4274 setKeyPool.insert(nIndex);
4275 }
f48742c2 4276 LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
37971fcc
GA
4277 }
4278 return true;
4279}
4280
13dd2d09 4281bool CWallet::TopUpKeyPool(unsigned int kpSize)
e8ef3da7 4282{
e8ef3da7 4283 {
f8dcd5ca
PW
4284 LOCK(cs_wallet);
4285
4e87d341
MC
4286 if (IsLocked())
4287 return false;
4288
e8ef3da7
WL
4289 CWalletDB walletdb(strWalletFile);
4290
4291 // Top up key pool
13dd2d09
JG
4292 unsigned int nTargetSize;
4293 if (kpSize > 0)
4294 nTargetSize = kpSize;
4295 else
51ed9ec9 4296 nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
13dd2d09 4297
faf705a4 4298 while (setKeyPool.size() < (nTargetSize + 1))
e8ef3da7 4299 {
51ed9ec9 4300 int64_t nEnd = 1;
e8ef3da7
WL
4301 if (!setKeyPool.empty())
4302 nEnd = *(--setKeyPool.end()) + 1;
4303 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
5262fde0 4304 throw runtime_error("TopUpKeyPool(): writing generated key failed");
e8ef3da7 4305 setKeyPool.insert(nEnd);
783b182c 4306 LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
e8ef3da7 4307 }
4e87d341
MC
4308 }
4309 return true;
4310}
4311
51ed9ec9 4312void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
4e87d341
MC
4313{
4314 nIndex = -1;
fd61d6f5 4315 keypool.vchPubKey = CPubKey();
4e87d341 4316 {
f8dcd5ca
PW
4317 LOCK(cs_wallet);
4318
4e87d341
MC
4319 if (!IsLocked())
4320 TopUpKeyPool();
e8ef3da7
WL
4321
4322 // Get the oldest key
4e87d341
MC
4323 if(setKeyPool.empty())
4324 return;
4325
4326 CWalletDB walletdb(strWalletFile);
4327
e8ef3da7
WL
4328 nIndex = *(setKeyPool.begin());
4329 setKeyPool.erase(setKeyPool.begin());
4330 if (!walletdb.ReadPool(nIndex, keypool))
5262fde0 4331 throw runtime_error("ReserveKeyFromKeyPool(): read failed");
fd61d6f5 4332 if (!HaveKey(keypool.vchPubKey.GetID()))
5262fde0 4333 throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
fd61d6f5 4334 assert(keypool.vchPubKey.IsValid());
36a65612 4335 //LogPrintf("keypool reserve %d\n", nIndex);
e8ef3da7
WL
4336 }
4337}
4338
51ed9ec9 4339void CWallet::KeepKey(int64_t nIndex)
e8ef3da7
WL
4340{
4341 // Remove from key pool
4342 if (fFileBacked)
4343 {
4344 CWalletDB walletdb(strWalletFile);
6cc4a62c 4345 walletdb.ErasePool(nIndex);
e8ef3da7 4346 }
f48742c2 4347 LogPrintf("keypool keep %d\n", nIndex);
e8ef3da7
WL
4348}
4349
51ed9ec9 4350void CWallet::ReturnKey(int64_t nIndex)
e8ef3da7
WL
4351{
4352 // Return to key pool
f8dcd5ca
PW
4353 {
4354 LOCK(cs_wallet);
e8ef3da7 4355 setKeyPool.insert(nIndex);
f8dcd5ca 4356 }
36a65612 4357 //LogPrintf("keypool return %d\n", nIndex);
e8ef3da7
WL
4358}
4359
71ac5052 4360bool CWallet::GetKeyFromPool(CPubKey& result)
e8ef3da7 4361{
51ed9ec9 4362 int64_t nIndex = 0;
e8ef3da7 4363 CKeyPool keypool;
7db3b75b 4364 {
f8dcd5ca 4365 LOCK(cs_wallet);
ed02c95d
GA
4366 ReserveKeyFromKeyPool(nIndex, keypool);
4367 if (nIndex == -1)
7db3b75b 4368 {
ed02c95d
GA
4369 if (IsLocked()) return false;
4370 result = GenerateNewKey();
7db3b75b
GA
4371 return true;
4372 }
ed02c95d
GA
4373 KeepKey(nIndex);
4374 result = keypool.vchPubKey;
7db3b75b 4375 }
7db3b75b 4376 return true;
e8ef3da7
WL
4377}
4378
51ed9ec9 4379int64_t CWallet::GetOldestKeyPoolTime()
e8ef3da7 4380{
51ed9ec9 4381 int64_t nIndex = 0;
e8ef3da7
WL
4382 CKeyPool keypool;
4383 ReserveKeyFromKeyPool(nIndex, keypool);
4e87d341
MC
4384 if (nIndex == -1)
4385 return GetTime();
e8ef3da7
WL
4386 ReturnKey(nIndex);
4387 return keypool.nTime;
4388}
4389
a372168e 4390std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
22dfd735 4391{
a372168e 4392 map<CTxDestination, CAmount> balances;
22dfd735 4393
4394 {
4395 LOCK(cs_wallet);
4396 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
4397 {
4398 CWalletTx *pcoin = &walletEntry.second;
4399
75a4d512 4400 if (!CheckFinalTx(*pcoin) || !pcoin->IsTrusted())
22dfd735 4401 continue;
4402
4403 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
4404 continue;
4405
4406 int nDepth = pcoin->GetDepthInMainChain();
a3e192a3 4407 if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
22dfd735 4408 continue;
4409
b1093efa 4410 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 4411 {
b1093efa 4412 CTxDestination addr;
22dfd735 4413 if (!IsMine(pcoin->vout[i]))
4414 continue;
b1093efa
GM
4415 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
4416 continue;
22dfd735 4417
a372168e 4418 CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
22dfd735 4419
22dfd735 4420 if (!balances.count(addr))
4421 balances[addr] = 0;
4422 balances[addr] += n;
4423 }
4424 }
4425 }
4426
4427 return balances;
4428}
4429
b1093efa 4430set< set<CTxDestination> > CWallet::GetAddressGroupings()
22dfd735 4431{
95691680 4432 AssertLockHeld(cs_wallet); // mapWallet
b1093efa
GM
4433 set< set<CTxDestination> > groupings;
4434 set<CTxDestination> grouping;
22dfd735 4435
4436 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
4437 {
4438 CWalletTx *pcoin = &walletEntry.second;
4439
a3fad211 4440 if (pcoin->vin.size() > 0)
22dfd735 4441 {
a3fad211 4442 bool any_mine = false;
22dfd735 4443 // group all input addresses with each other
4444 BOOST_FOREACH(CTxIn txin, pcoin->vin)
b1093efa
GM
4445 {
4446 CTxDestination address;
a3fad211
GM
4447 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
4448 continue;
b1093efa
GM
4449 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
4450 continue;
4451 grouping.insert(address);
a3fad211 4452 any_mine = true;
b1093efa 4453 }
22dfd735 4454
4455 // group change with input addresses
a3fad211
GM
4456 if (any_mine)
4457 {
4458 BOOST_FOREACH(CTxOut txout, pcoin->vout)
4459 if (IsChange(txout))
4460 {
4461 CTxDestination txoutAddr;
4462 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
4463 continue;
4464 grouping.insert(txoutAddr);
4465 }
4466 }
4467 if (grouping.size() > 0)
4468 {
4469 groupings.insert(grouping);
4470 grouping.clear();
4471 }
22dfd735 4472 }
4473
4474 // group lone addrs by themselves
b1093efa 4475 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
22dfd735 4476 if (IsMine(pcoin->vout[i]))
4477 {
b1093efa
GM
4478 CTxDestination address;
4479 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
4480 continue;
4481 grouping.insert(address);
22dfd735 4482 groupings.insert(grouping);
4483 grouping.clear();
4484 }
4485 }
4486
b1093efa
GM
4487 set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
4488 map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
4489 BOOST_FOREACH(set<CTxDestination> grouping, groupings)
22dfd735 4490 {
4491 // make a set of all the groups hit by this new group
b1093efa
GM
4492 set< set<CTxDestination>* > hits;
4493 map< CTxDestination, set<CTxDestination>* >::iterator it;
4494 BOOST_FOREACH(CTxDestination address, grouping)
22dfd735 4495 if ((it = setmap.find(address)) != setmap.end())
4496 hits.insert((*it).second);
4497
4498 // merge all hit groups into a new single group and delete old groups
b1093efa
GM
4499 set<CTxDestination>* merged = new set<CTxDestination>(grouping);
4500 BOOST_FOREACH(set<CTxDestination>* hit, hits)
22dfd735 4501 {
4502 merged->insert(hit->begin(), hit->end());
4503 uniqueGroupings.erase(hit);
4504 delete hit;
4505 }
4506 uniqueGroupings.insert(merged);
4507
4508 // update setmap
b1093efa 4509 BOOST_FOREACH(CTxDestination element, *merged)
22dfd735 4510 setmap[element] = merged;
4511 }
4512
b1093efa
GM
4513 set< set<CTxDestination> > ret;
4514 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
22dfd735 4515 {
4516 ret.insert(*uniqueGrouping);
4517 delete uniqueGrouping;
4518 }
4519
4520 return ret;
4521}
4522
db954a65 4523std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
3624356e 4524{
43422a01 4525 LOCK(cs_wallet);
3624356e
GA
4526 set<CTxDestination> result;
4527 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
4528 {
4529 const CTxDestination& address = item.first;
4530 const string& strName = item.second.name;
4531 if (strName == strAccount)
4532 result.insert(address);
4533 }
4534 return result;
4535}
4536
360cfe14 4537bool CReserveKey::GetReservedKey(CPubKey& pubkey)
e8ef3da7
WL
4538{
4539 if (nIndex == -1)
4540 {
4541 CKeyPool keypool;
4542 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
0d7b28e5
MC
4543 if (nIndex != -1)
4544 vchPubKey = keypool.vchPubKey;
360cfe14 4545 else {
6c37f7fd 4546 return false;
cee69980 4547 }
e8ef3da7 4548 }
fd61d6f5 4549 assert(vchPubKey.IsValid());
360cfe14
PW
4550 pubkey = vchPubKey;
4551 return true;
e8ef3da7
WL
4552}
4553
4554void CReserveKey::KeepKey()
4555{
4556 if (nIndex != -1)
4557 pwallet->KeepKey(nIndex);
4558 nIndex = -1;
fd61d6f5 4559 vchPubKey = CPubKey();
e8ef3da7
WL
4560}
4561
4562void CReserveKey::ReturnKey()
4563{
4564 if (nIndex != -1)
4565 pwallet->ReturnKey(nIndex);
4566 nIndex = -1;
fd61d6f5 4567 vchPubKey = CPubKey();
e8ef3da7 4568}
ae3d0aba 4569
434e4273 4570void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
30ab2c9c
PW
4571{
4572 setAddress.clear();
4573
4574 CWalletDB walletdb(strWalletFile);
4575
f8dcd5ca 4576 LOCK2(cs_main, cs_wallet);
51ed9ec9 4577 BOOST_FOREACH(const int64_t& id, setKeyPool)
30ab2c9c
PW
4578 {
4579 CKeyPool keypool;
4580 if (!walletdb.ReadPool(id, keypool))
5262fde0 4581 throw runtime_error("GetAllReserveKeyHashes(): read failed");
fd61d6f5 4582 assert(keypool.vchPubKey.IsValid());
10254401
PW
4583 CKeyID keyID = keypool.vchPubKey.GetID();
4584 if (!HaveKey(keyID))
5262fde0 4585 throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
10254401 4586 setAddress.insert(keyID);
30ab2c9c
PW
4587 }
4588}
fe4a6550
WL
4589
4590void CWallet::UpdatedTransaction(const uint256 &hashTx)
4591{
4592 {
4593 LOCK(cs_wallet);
4594 // Only notify UI if this transaction is in this wallet
4595 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
4596 if (mi != mapWallet.end())
4597 NotifyTransactionChanged(this, hashTx, CT_UPDATED);
4598 }
4599}
fdbb537d
JG
4600
4601void CWallet::LockCoin(COutPoint& output)
4602{
95691680 4603 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
4604 setLockedCoins.insert(output);
4605}
4606
4607void CWallet::UnlockCoin(COutPoint& output)
4608{
95691680 4609 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
4610 setLockedCoins.erase(output);
4611}
4612
4613void CWallet::UnlockAllCoins()
4614{
95691680 4615 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
4616 setLockedCoins.clear();
4617}
4618
4619bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
4620{
95691680 4621 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
4622 COutPoint outpt(hash, n);
4623
4624 return (setLockedCoins.count(outpt) > 0);
4625}
4626
4627void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
4628{
95691680 4629 AssertLockHeld(cs_wallet); // setLockedCoins
fdbb537d
JG
4630 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
4631 it != setLockedCoins.end(); it++) {
4632 COutPoint outpt = (*it);
4633 vOutpts.push_back(outpt);
4634 }
4635}
4636
98a4f6a6
BM
4637
4638// Note Locking Operations
4639
e935beb8 4640void CWallet::LockNote(const JSOutPoint& output)
98a4f6a6 4641{
d358d145
S
4642 AssertLockHeld(cs_wallet); // setLockedSproutNotes
4643 setLockedSproutNotes.insert(output);
98a4f6a6
BM
4644}
4645
e935beb8 4646void CWallet::UnlockNote(const JSOutPoint& output)
98a4f6a6 4647{
d358d145
S
4648 AssertLockHeld(cs_wallet); // setLockedSproutNotes
4649 setLockedSproutNotes.erase(output);
98a4f6a6
BM
4650}
4651
9ae73247 4652void CWallet::UnlockAllSproutNotes()
98a4f6a6 4653{
d358d145
S
4654 AssertLockHeld(cs_wallet); // setLockedSproutNotes
4655 setLockedSproutNotes.clear();
98a4f6a6
BM
4656}
4657
e935beb8 4658bool CWallet::IsLockedNote(const JSOutPoint& outpt) const
98a4f6a6 4659{
d358d145 4660 AssertLockHeld(cs_wallet); // setLockedSproutNotes
98a4f6a6 4661
d358d145 4662 return (setLockedSproutNotes.count(outpt) > 0);
98a4f6a6
BM
4663}
4664
0f62cacf 4665std::vector<JSOutPoint> CWallet::ListLockedSproutNotes()
98a4f6a6 4666{
d358d145
S
4667 AssertLockHeld(cs_wallet); // setLockedSproutNotes
4668 std::vector<JSOutPoint> vOutpts(setLockedSproutNotes.begin(), setLockedSproutNotes.end());
98a4f6a6
BM
4669 return vOutpts;
4670}
4671
b1c693e5
S
4672void CWallet::LockNote(const SaplingOutPoint& output)
4673{
4674 AssertLockHeld(cs_wallet);
4675 setLockedSaplingNotes.insert(output);
4676}
4677
4678void CWallet::UnlockNote(const SaplingOutPoint& output)
4679{
4680 AssertLockHeld(cs_wallet);
4681 setLockedSaplingNotes.erase(output);
4682}
4683
4684void CWallet::UnlockAllSaplingNotes()
4685{
4686 AssertLockHeld(cs_wallet);
4687 setLockedSaplingNotes.clear();
4688}
4689
4690bool CWallet::IsLockedNote(const SaplingOutPoint& output) const
4691{
4692 AssertLockHeld(cs_wallet);
4693 return (setLockedSaplingNotes.count(output) > 0);
4694}
4695
4696std::vector<SaplingOutPoint> CWallet::ListLockedSaplingNotes()
4697{
4698 AssertLockHeld(cs_wallet);
4699 std::vector<SaplingOutPoint> vOutputs(setLockedSaplingNotes.begin(), setLockedSaplingNotes.end());
4700 return vOutputs;
4701}
4702
5b40d886 4703/** @} */ // end of Actions
8b59a3d3 4704
4705class CAffectedKeysVisitor : public boost::static_visitor<void> {
4706private:
4707 const CKeyStore &keystore;
4708 std::vector<CKeyID> &vKeys;
4709
4710public:
4711 CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
4712
4713 void Process(const CScript &script) {
4714 txnouttype type;
4715 std::vector<CTxDestination> vDest;
4716 int nRequired;
4717 if (ExtractDestinations(script, type, vDest, nRequired)) {
4718 BOOST_FOREACH(const CTxDestination &dest, vDest)
4719 boost::apply_visitor(*this, dest);
4720 }
4721 }
4722
4723 void operator()(const CKeyID &keyId) {
4724 if (keystore.HaveKey(keyId))
4725 vKeys.push_back(keyId);
4726 }
4727
b8deecdc 4728 void operator()(const CPubKey &key) {
4729 CKeyID keyId = key.GetID();
4730 if (keystore.HaveKey(keyId))
4731 vKeys.push_back(keyId);
4732 }
4733
8b59a3d3 4734 void operator()(const CScriptID &scriptId) {
4735 CScript script;
4736 if (keystore.GetCScript(scriptId, script))
4737 Process(script);
4738 }
4739
4740 void operator()(const CNoDestination &none) {}
4741};
4742
51ed9ec9 4743void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
95691680 4744 AssertLockHeld(cs_wallet); // mapKeyMetadata
434e4273
PW
4745 mapKeyBirth.clear();
4746
4747 // get birth times for keys with metadata
4748 for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
4749 if (it->second.nCreateTime)
4750 mapKeyBirth[it->first] = it->second.nCreateTime;
4751
4752 // map in which we'll infer heights of other keys
4c6d41b8 4753 CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
434e4273
PW
4754 std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
4755 std::set<CKeyID> setKeys;
4756 GetKeys(setKeys);
4757 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
4758 if (mapKeyBirth.count(keyid) == 0)
4759 mapKeyFirstBlock[keyid] = pindexMax;
4760 }
4761 setKeys.clear();
4762
4763 // if there are no such keys, we're done
4764 if (mapKeyFirstBlock.empty())
4765 return;
4766
4767 // find first block that affects those keys, if there are any left
4768 std::vector<CKeyID> vAffected;
4769 for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
4770 // iterate over all wallet transactions...
4771 const CWalletTx &wtx = (*it).second;
145d5be8 4772 BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
4c6d41b8 4773 if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
434e4273 4774 // ... which are already in a block
4b729ec5 4775 int nHeight = blit->second->GetHeight();
434e4273
PW
4776 BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
4777 // iterate over all their outputs
8b59a3d3 4778 CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
434e4273
PW
4779 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
4780 // ... and all their affected keys
4781 std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
4b729ec5 4782 if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->GetHeight())
434e4273
PW
4783 rit->second = blit->second;
4784 }
4785 vAffected.clear();
4786 }
4787 }
4788 }
4789
4790 // Extract block timestamps for those keys
4791 for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
209377a7 4792 mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
434e4273 4793}
b10e1470
WL
4794
4795bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
4796{
8476d5d4
CL
4797 if (boost::get<CNoDestination>(&dest))
4798 return false;
4799
b10e1470
WL
4800 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
4801 if (!fFileBacked)
4802 return true;
07444da1 4803 return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value);
b10e1470
WL
4804}
4805
4806bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
4807{
4808 if (!mapAddressBook[dest].destdata.erase(key))
4809 return false;
4810 if (!fFileBacked)
4811 return true;
07444da1 4812 return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key);
b10e1470
WL
4813}
4814
4815bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
4816{
4817 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
4818 return true;
4819}
4820
4821bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
4822{
4823 std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
4824 if(i != mapAddressBook.end())
4825 {
4826 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
4827 if(j != i->second.destdata.end())
4828 {
4829 if(value)
4830 *value = j->second;
4831 return true;
4832 }
4833 }
4834 return false;
4835}
af8297c0
WL
4836
4837CKeyPool::CKeyPool()
4838{
4839 nTime = GetTime();
4840}
4841
4842CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
4843{
4844 nTime = GetTime();
4845 vchPubKey = vchPubKeyIn;
4846}
4847
4848CWalletKey::CWalletKey(int64_t nExpires)
4849{
4850 nTimeCreated = (nExpires ? GetTime() : 0);
4851 nTimeExpires = nExpires;
4852}
0101483f 4853
4b0deb3b 4854int CMerkleTx::SetMerkleBranch(const CBlock& block)
0101483f
WL
4855{
4856 AssertLockHeld(cs_main);
4857 CBlock blockTmp;
4858
4b0deb3b
DK
4859 // Update the tx's hashBlock
4860 hashBlock = block.GetHash();
0101483f 4861
4b0deb3b
DK
4862 // Locate the transaction
4863 for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
4864 if (block.vtx[nIndex] == *(CTransaction*)this)
4865 break;
4866 if (nIndex == (int)block.vtx.size())
4867 {
4868 vMerkleBranch.clear();
4869 nIndex = -1;
5262fde0 4870 LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
4b0deb3b 4871 return 0;
0101483f
WL
4872 }
4873
4b0deb3b
DK
4874 // Fill in merkle branch
4875 vMerkleBranch = block.GetMerkleBranch(nIndex);
4876
0101483f 4877 // Is the tx in a block that's in the main chain
145d5be8 4878 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
0101483f
WL
4879 if (mi == mapBlockIndex.end())
4880 return 0;
4b0deb3b 4881 const CBlockIndex* pindex = (*mi).second;
0101483f
WL
4882 if (!pindex || !chainActive.Contains(pindex))
4883 return 0;
4884
4b729ec5 4885 return chainActive.Height() - pindex->GetHeight() + 1;
0101483f
WL
4886}
4887
a31e8bad 4888int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
0101483f 4889{
4f152496 4890 if (hashBlock.IsNull() || nIndex == -1)
0101483f
WL
4891 return 0;
4892 AssertLockHeld(cs_main);
4893
4894 // Find the block it claims to be in
145d5be8 4895 BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
0101483f
WL
4896 if (mi == mapBlockIndex.end())
4897 return 0;
4898 CBlockIndex* pindex = (*mi).second;
4899 if (!pindex || !chainActive.Contains(pindex))
4900 return 0;
4901
4902 // Make sure the merkle branch connects to this block
4903 if (!fMerkleVerified)
4904 {
805344dc 4905 if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
0101483f
WL
4906 return 0;
4907 fMerkleVerified = true;
4908 }
4909
4910 pindexRet = pindex;
4b729ec5 4911 return chainActive.Height() - pindex->GetHeight() + 1;
0101483f
WL
4912}
4913
a31e8bad 4914int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
0101483f
WL
4915{
4916 AssertLockHeld(cs_main);
4917 int nResult = GetDepthInMainChainINTERNAL(pindexRet);
805344dc 4918 if (nResult == 0 && !mempool.exists(GetHash()))
0101483f
WL
4919 return -1; // Not in chain, not in mempool
4920
4921 return nResult;
4922}
4923
4924int CMerkleTx::GetBlocksToMaturity() const
4925{
7a90b9dd 4926 if ( ASSETCHAINS_SYMBOL[0] == 0 )
4927 COINBASE_MATURITY = _COINBASE_MATURITY;
0101483f
WL
4928 if (!IsCoinBase())
4929 return 0;
39267c35 4930 int32_t depth = GetDepthInMainChain();
204cf3fc 4931 int32_t ut = UnlockTime(0);
c2f6623f 4932 int32_t toMaturity = (ut - chainActive.Height()) < 0 ? 0 : ut - chainActive.Height();
4933 //printf("depth.%i, unlockTime.%i, toMaturity.%i\n", depth, ut, toMaturity);
4934 ut = (COINBASE_MATURITY - depth) < 0 ? 0 : COINBASE_MATURITY - depth;
204cf3fc 4935 return(ut < toMaturity ? toMaturity : ut);
0101483f
WL
4936}
4937
1371e6f5 4938bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
0101483f
WL
4939{
4940 CValidationState state;
1371e6f5 4941 return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
0101483f
WL
4942}
4943
cb0d208f
S
4944/**
4945 * Find notes in the wallet filtered by payment address, min depth and ability to spend.
4946 * These notes are decrypted and added to the output parameter vector, outEntries.
4947 */
94e99acd
JG
4948void CWallet::GetFilteredNotes(
4949 std::vector<CSproutNotePlaintextEntry>& sproutEntries,
4950 std::vector<SaplingNoteEntry>& saplingEntries,
4951 std::string address,
4952 int minDepth,
4953 bool ignoreSpent,
ef27d7e4 4954 bool requireSpendingKey)
a5ac2e25 4955{
bdbe8e85
JG
4956 std::set<PaymentAddress> filterAddresses;
4957
a5ac2e25 4958 if (address.length() > 0) {
e5eab182 4959 filterAddresses.insert(DecodePaymentAddress(address));
a5ac2e25
S
4960 }
4961
ef27d7e4 4962 GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey);
bdbe8e85
JG
4963}
4964
4965/**
095eee4f
EOW
4966 * Find notes in the wallet filtered by payment addresses, min depth, max depth,
4967 * if the note is spent, if a spending key is required, and if the notes are locked.
bdbe8e85
JG
4968 * These notes are decrypted and added to the output parameter vector, outEntries.
4969 */
4970void CWallet::GetFilteredNotes(
94e99acd
JG
4971 std::vector<CSproutNotePlaintextEntry>& sproutEntries,
4972 std::vector<SaplingNoteEntry>& saplingEntries,
bdbe8e85
JG
4973 std::set<PaymentAddress>& filterAddresses,
4974 int minDepth,
ef27d7e4 4975 int maxDepth,
bdbe8e85 4976 bool ignoreSpent,
ef27d7e4
EOW
4977 bool requireSpendingKey,
4978 bool ignoreLocked)
bdbe8e85 4979{
a5ac2e25
S
4980 LOCK2(cs_main, cs_wallet);
4981
4982 for (auto & p : mapWallet) {
4983 CWalletTx wtx = p.second;
4984
4985 // Filter the transactions before checking for notes
095eee4f
EOW
4986 if (!CheckFinalTx(wtx) ||
4987 wtx.GetBlocksToMaturity() > 0 ||
4988 wtx.GetDepthInMainChain() < minDepth ||
4989 wtx.GetDepthInMainChain() > maxDepth) {
a5ac2e25
S
4990 continue;
4991 }
4992
005f3ad1 4993 for (auto & pair : wtx.mapSproutNoteData) {
a5ac2e25 4994 JSOutPoint jsop = pair.first;
005f3ad1 4995 SproutNoteData nd = pair.second;
e5eab182 4996 SproutPaymentAddress pa = nd.address;
a5ac2e25
S
4997
4998 // skip notes which belong to a different payment address in the wallet
bdbe8e85 4999 if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
a5ac2e25
S
5000 continue;
5001 }
5002
5003 // skip note which has been spent
3b6dd486 5004 if (ignoreSpent && nd.nullifier && IsSproutSpent(*nd.nullifier)) {
a5ac2e25
S
5005 continue;
5006 }
5007
9a2b8ae5 5008 // skip notes which cannot be spent
ef27d7e4 5009 if (requireSpendingKey && !HaveSproutSpendingKey(pa)) {
9a2b8ae5
JG
5010 continue;
5011 }
efb7662d 5012
4e6400bc 5013 // skip locked notes
ef27d7e4 5014 if (ignoreLocked && IsLockedNote(jsop)) {
4e6400bc
BM
5015 continue;
5016 }
9a2b8ae5 5017
a5ac2e25
S
5018 int i = jsop.js; // Index into CTransaction.vjoinsplit
5019 int j = jsop.n; // Index into JSDescription.ciphertexts
5020
5021 // Get cached decryptor
5022 ZCNoteDecryption decryptor;
5023 if (!GetNoteDecryptor(pa, decryptor)) {
5024 // Note decryptors are created when the wallet is loaded, so it should always exist
80ed13d5 5025 throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa)));
a5ac2e25
S
5026 }
5027
5028 // determine amount of funds in the note
5029 auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
5030 try {
5020a936 5031 SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
a5ac2e25
S
5032 decryptor,
5033 wtx.vjoinsplit[i].ciphertexts[j],
5034 wtx.vjoinsplit[i].ephemeralKey,
5035 hSig,
5036 (unsigned char) j);
5037
9396b85d 5038 sproutEntries.push_back(CSproutNotePlaintextEntry{jsop, pa, plaintext, wtx.GetDepthInMainChain()});
a5ac2e25 5039
51fde9ea 5040 } catch (const note_decryption_failed &err) {
a5ac2e25 5041 // Couldn't decrypt with this spending key
80ed13d5 5042 throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa)));
51fde9ea
JG
5043 } catch (const std::exception &exc) {
5044 // Unexpected failure
80ed13d5 5045 throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
a5ac2e25
S
5046 }
5047 }
94e99acd
JG
5048
5049 for (auto & pair : wtx.mapSaplingNoteData) {
5050 SaplingOutPoint op = pair.first;
5051 SaplingNoteData nd = pair.second;
5052
5053 auto maybe_pt = SaplingNotePlaintext::decrypt(
5054 wtx.vShieldedOutput[op.n].encCiphertext,
5055 nd.ivk,
5056 wtx.vShieldedOutput[op.n].ephemeralKey,
5057 wtx.vShieldedOutput[op.n].cm);
5058 assert(static_cast<bool>(maybe_pt));
5059 auto notePt = maybe_pt.get();
5060
5061 auto maybe_pa = nd.ivk.address(notePt.d);
5062 assert(static_cast<bool>(maybe_pa));
5063 auto pa = maybe_pa.get();
5064
5065 // skip notes which belong to a different payment address in the wallet
5066 if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
5067 continue;
5068 }
5069
5070 if (ignoreSpent && nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
5071 continue;
5072 }
5073
5074 // skip notes which cannot be spent
ef27d7e4 5075 if (requireSpendingKey) {
94e99acd
JG
5076 libzcash::SaplingIncomingViewingKey ivk;
5077 libzcash::SaplingFullViewingKey fvk;
5078 if (!(GetSaplingIncomingViewingKey(pa, ivk) &&
5079 GetSaplingFullViewingKey(ivk, fvk) &&
5080 HaveSaplingSpendingKey(fvk))) {
5081 continue;
5082 }
5083 }
5084
5085 // skip locked notes
5086 // TODO: Add locking for Sapling notes
ef27d7e4 5087 // if (ignoreLocked && IsLockedNote(op)) {
94e99acd
JG
5088 // continue;
5089 // }
5090
5091 auto note = notePt.note(nd.ivk).get();
5092 saplingEntries.push_back(SaplingNoteEntry {
94e99acd
JG
5093 op, pa, note, notePt.memo(), wtx.GetDepthInMainChain() });
5094 }
d72c19a6
S
5095 }
5096}
5097
d72c19a6 5098
053cb349
JG
5099//
5100// Shielded key and address generalizations
5101//
5102
5103bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const
5104{
5105 return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr);
5106}
5107
5108bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
5109{
5110 libzcash::SaplingIncomingViewingKey ivk;
5111
70b4ad2d
JG
5112 // If we have a SaplingExtendedSpendingKey in the wallet, then we will
5113 // also have the corresponding SaplingFullViewingKey.
053cb349
JG
5114 return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
5115 m_wallet->HaveSaplingFullViewingKey(ivk);
5116}
5117
5118bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
5119{
5120 return false;
5121}
e22c115e 5122
81e0fd2e
JG
5123bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const
5124{
5125 return m_wallet->HaveSproutSpendingKey(zaddr);
5126}
5127
5128bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
5129{
5130 libzcash::SaplingIncomingViewingKey ivk;
5131 libzcash::SaplingFullViewingKey fvk;
5132
5133 return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
5134 m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
5135 m_wallet->HaveSaplingSpendingKey(fvk);
5136}
5137
5138bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncoding& no) const
5139{
5140 return false;
5141}
5142
e22c115e
JG
5143boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
5144 const libzcash::SproutPaymentAddress &zaddr) const
5145{
5146 libzcash::SproutSpendingKey k;
5147 if (m_wallet->GetSproutSpendingKey(zaddr, k)) {
5148 return libzcash::SpendingKey(k);
5149 } else {
5150 return boost::none;
a5ac2e25
S
5151 }
5152}
e22c115e
JG
5153
5154boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
5155 const libzcash::SaplingPaymentAddress &zaddr) const
5156{
5e360fb2
EOW
5157 libzcash::SaplingExtendedSpendingKey extsk;
5158 if (m_wallet->GetSaplingExtendedSpendingKey(zaddr, extsk)) {
5159 return libzcash::SpendingKey(extsk);
e22c115e
JG
5160 } else {
5161 return boost::none;
5162 }
5163}
5164
5165boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
5166 const libzcash::InvalidEncoding& no) const
5167{
5168 // Defaults to InvalidEncoding
5169 return libzcash::SpendingKey();
5170}
fcab001b 5171
0f03de55 5172SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
2fe39561 5173 auto addr = sk.address();
9bcf90e2
EOW
5174 if (log){
5175 LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
5176 }
fcab001b 5177 if (m_wallet->HaveSproutSpendingKey(addr)) {
0f03de55
EOW
5178 return KeyAlreadyExists;
5179 } else if (m_wallet-> AddSproutZKey(sk)) {
9bcf90e2 5180 m_wallet->mapSproutZKeyMetadata[addr].nCreateTime = nTime;
0f03de55
EOW
5181 return KeyAdded;
5182 } else {
5183 return KeyNotAdded;
fcab001b
EOW
5184 }
5185}
5186
0f03de55 5187SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
fcab001b
EOW
5188 auto fvk = sk.expsk.full_viewing_key();
5189 auto ivk = fvk.in_viewing_key();
5190 auto addr = sk.DefaultAddress();
5191 {
9bcf90e2
EOW
5192 if (log){
5193 LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
5194 }
fcab001b
EOW
5195 // Don't throw error in case a key is already there
5196 if (m_wallet->HaveSaplingSpendingKey(fvk)) {
0f03de55 5197 return KeyAlreadyExists;
fcab001b 5198 } else {
fcab001b 5199 if (!m_wallet-> AddSaplingZKey(sk, addr)) {
0f03de55 5200 return KeyNotAdded;
fcab001b
EOW
5201 }
5202
5203 // Sapling addresses can't have been used in transactions prior to activation.
5204 if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) {
9bcf90e2 5205 m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime;
fcab001b 5206 } else {
9bcf90e2
EOW
5207 // 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
5208 m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
fcab001b 5209 }
2fe39561
EOW
5210 if (hdKeypath) {
5211 m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
5212 }
5213 if (seedFpStr) {
5214 uint256 seedFp;
5215 seedFp.SetHex(seedFpStr.get());
5216 m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
5217 }
0f03de55 5218 return KeyAdded;
fcab001b
EOW
5219 }
5220 }
5221}
5222
0f03de55 5223SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
fcab001b
EOW
5224 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
5225}
This page took 1.576822 seconds and 4 git commands to generate.