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