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