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