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