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