]> Git Repo - VerusCoin.git/blame_incremental - src/wallet.cpp
Merge pull request #4100
[VerusCoin.git] / src / wallet.cpp
... / ...
CommitLineData
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2014 The Bitcoin developers
3// Distributed under the MIT/X11 software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "wallet.h"
7
8#include "base58.h"
9#include "checkpoints.h"
10#include "coincontrol.h"
11#include "net.h"
12
13#include <boost/algorithm/string/replace.hpp>
14#include <openssl/rand.h>
15
16using namespace std;
17
18// Settings
19CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
20bool bSpendZeroConfChange = true;
21
22//////////////////////////////////////////////////////////////////////////////
23//
24// mapWallet
25//
26
27struct CompareValueOnly
28{
29 bool operator()(const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t1,
30 const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t2) const
31 {
32 return t1.first < t2.first;
33 }
34};
35
36const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
37{
38 LOCK(cs_wallet);
39 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
40 if (it == mapWallet.end())
41 return NULL;
42 return &(it->second);
43}
44
45CPubKey CWallet::GenerateNewKey()
46{
47 AssertLockHeld(cs_wallet); // mapKeyMetadata
48 bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
49
50 RandAddSeedPerfmon();
51 CKey secret;
52 secret.MakeNewKey(fCompressed);
53
54 // Compressed public keys were introduced in version 0.6.0
55 if (fCompressed)
56 SetMinVersion(FEATURE_COMPRPUBKEY);
57
58 CPubKey pubkey = secret.GetPubKey();
59
60 // Create new metadata
61 int64_t nCreationTime = GetTime();
62 mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
63 if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
64 nTimeFirstKey = nCreationTime;
65
66 if (!AddKeyPubKey(secret, pubkey))
67 throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
68 return pubkey;
69}
70
71bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
72{
73 AssertLockHeld(cs_wallet); // mapKeyMetadata
74 if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
75 return false;
76 if (!fFileBacked)
77 return true;
78 if (!IsCrypted()) {
79 return CWalletDB(strWalletFile).WriteKey(pubkey,
80 secret.GetPrivKey(),
81 mapKeyMetadata[pubkey.GetID()]);
82 }
83 return true;
84}
85
86bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
87 const vector<unsigned char> &vchCryptedSecret)
88{
89 if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
90 return false;
91 if (!fFileBacked)
92 return true;
93 {
94 LOCK(cs_wallet);
95 if (pwalletdbEncryption)
96 return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
97 vchCryptedSecret,
98 mapKeyMetadata[vchPubKey.GetID()]);
99 else
100 return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
101 vchCryptedSecret,
102 mapKeyMetadata[vchPubKey.GetID()]);
103 }
104 return false;
105}
106
107bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
108{
109 AssertLockHeld(cs_wallet); // mapKeyMetadata
110 if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
111 nTimeFirstKey = meta.nCreateTime;
112
113 mapKeyMetadata[pubkey.GetID()] = meta;
114 return true;
115}
116
117bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
118{
119 return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
120}
121
122bool CWallet::AddCScript(const CScript& redeemScript)
123{
124 if (!CCryptoKeyStore::AddCScript(redeemScript))
125 return false;
126 if (!fFileBacked)
127 return true;
128 return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
129}
130
131bool CWallet::LoadCScript(const CScript& redeemScript)
132{
133 /* A sanity check was added in pull #3843 to avoid adding redeemScripts
134 * that never can be redeemed. However, old wallets may still contain
135 * these. Do not add them to the wallet and warn. */
136 if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
137 {
138 std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString();
139 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",
140 __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
141 return true;
142 }
143
144 return CCryptoKeyStore::AddCScript(redeemScript);
145}
146
147bool CWallet::Unlock(const SecureString& strWalletPassphrase)
148{
149 CCrypter crypter;
150 CKeyingMaterial vMasterKey;
151
152 {
153 LOCK(cs_wallet);
154 BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
155 {
156 if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
157 return false;
158 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
159 continue; // try another master key
160 if (CCryptoKeyStore::Unlock(vMasterKey))
161 return true;
162 }
163 }
164 return false;
165}
166
167bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
168{
169 bool fWasLocked = IsLocked();
170
171 {
172 LOCK(cs_wallet);
173 Lock();
174
175 CCrypter crypter;
176 CKeyingMaterial vMasterKey;
177 BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
178 {
179 if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
180 return false;
181 if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
182 return false;
183 if (CCryptoKeyStore::Unlock(vMasterKey))
184 {
185 int64_t nStartTime = GetTimeMillis();
186 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
187 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
188
189 nStartTime = GetTimeMillis();
190 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
191 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
192
193 if (pMasterKey.second.nDeriveIterations < 25000)
194 pMasterKey.second.nDeriveIterations = 25000;
195
196 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
197
198 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
199 return false;
200 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
201 return false;
202 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
203 if (fWasLocked)
204 Lock();
205 return true;
206 }
207 }
208 }
209
210 return false;
211}
212
213void CWallet::SetBestChain(const CBlockLocator& loc)
214{
215 CWalletDB walletdb(strWalletFile);
216 walletdb.WriteBestBlock(loc);
217}
218
219bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
220{
221 LOCK(cs_wallet); // nWalletVersion
222 if (nWalletVersion >= nVersion)
223 return true;
224
225 // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
226 if (fExplicit && nVersion > nWalletMaxVersion)
227 nVersion = FEATURE_LATEST;
228
229 nWalletVersion = nVersion;
230
231 if (nVersion > nWalletMaxVersion)
232 nWalletMaxVersion = nVersion;
233
234 if (fFileBacked)
235 {
236 CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
237 if (nWalletVersion > 40000)
238 pwalletdb->WriteMinVersion(nWalletVersion);
239 if (!pwalletdbIn)
240 delete pwalletdb;
241 }
242
243 return true;
244}
245
246bool CWallet::SetMaxVersion(int nVersion)
247{
248 LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
249 // cannot downgrade below current version
250 if (nWalletVersion > nVersion)
251 return false;
252
253 nWalletMaxVersion = nVersion;
254
255 return true;
256}
257
258set<uint256> CWallet::GetConflicts(const uint256& txid) const
259{
260 set<uint256> result;
261 AssertLockHeld(cs_wallet);
262
263 std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
264 if (it == mapWallet.end())
265 return result;
266 const CWalletTx& wtx = it->second;
267
268 std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
269
270 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
271 {
272 if (mapTxSpends.count(txin.prevout) <= 1)
273 continue; // No conflict if zero or one spends
274 range = mapTxSpends.equal_range(txin.prevout);
275 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
276 result.insert(it->second);
277 }
278 return result;
279}
280
281void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
282{
283 // We want all the wallet transactions in range to have the same metadata as
284 // the oldest (smallest nOrderPos).
285 // So: find smallest nOrderPos:
286
287 int nMinOrderPos = std::numeric_limits<int>::max();
288 const CWalletTx* copyFrom = NULL;
289 for (TxSpends::iterator it = range.first; it != range.second; ++it)
290 {
291 const uint256& hash = it->second;
292 int n = mapWallet[hash].nOrderPos;
293 if (n < nMinOrderPos)
294 {
295 nMinOrderPos = n;
296 copyFrom = &mapWallet[hash];
297 }
298 }
299 // Now copy data from copyFrom to rest:
300 for (TxSpends::iterator it = range.first; it != range.second; ++it)
301 {
302 const uint256& hash = it->second;
303 CWalletTx* copyTo = &mapWallet[hash];
304 if (copyFrom == copyTo) continue;
305 copyTo->mapValue = copyFrom->mapValue;
306 copyTo->vOrderForm = copyFrom->vOrderForm;
307 // fTimeReceivedIsTxTime not copied on purpose
308 // nTimeReceived not copied on purpose
309 copyTo->nTimeSmart = copyFrom->nTimeSmart;
310 copyTo->fFromMe = copyFrom->fFromMe;
311 copyTo->strFromAccount = copyFrom->strFromAccount;
312 // nOrderPos not copied on purpose
313 // cached members not copied on purpose
314 }
315}
316
317// Outpoint is spent if any non-conflicted transaction
318// spends it:
319bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
320{
321 const COutPoint outpoint(hash, n);
322 pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
323 range = mapTxSpends.equal_range(outpoint);
324
325 for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
326 {
327 const uint256& wtxid = it->second;
328 std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
329 if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
330 return true; // Spent
331 }
332 return false;
333}
334
335void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
336{
337 mapTxSpends.insert(make_pair(outpoint, wtxid));
338
339 pair<TxSpends::iterator, TxSpends::iterator> range;
340 range = mapTxSpends.equal_range(outpoint);
341 SyncMetaData(range);
342}
343
344
345void CWallet::AddToSpends(const uint256& wtxid)
346{
347 assert(mapWallet.count(wtxid));
348 CWalletTx& thisTx = mapWallet[wtxid];
349 if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
350 return;
351
352 BOOST_FOREACH(const CTxIn& txin, thisTx.vin)
353 AddToSpends(txin.prevout, wtxid);
354}
355
356bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
357{
358 if (IsCrypted())
359 return false;
360
361 CKeyingMaterial vMasterKey;
362 RandAddSeedPerfmon();
363
364 vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
365 RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
366
367 CMasterKey kMasterKey;
368
369 RandAddSeedPerfmon();
370 kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
371 RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
372
373 CCrypter crypter;
374 int64_t nStartTime = GetTimeMillis();
375 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
376 kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
377
378 nStartTime = GetTimeMillis();
379 crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
380 kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
381
382 if (kMasterKey.nDeriveIterations < 25000)
383 kMasterKey.nDeriveIterations = 25000;
384
385 LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
386
387 if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
388 return false;
389 if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
390 return false;
391
392 {
393 LOCK(cs_wallet);
394 mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
395 if (fFileBacked)
396 {
397 pwalletdbEncryption = new CWalletDB(strWalletFile);
398 if (!pwalletdbEncryption->TxnBegin())
399 return false;
400 pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
401 }
402
403 if (!EncryptKeys(vMasterKey))
404 {
405 if (fFileBacked)
406 pwalletdbEncryption->TxnAbort();
407 exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
408 }
409
410 // Encryption was introduced in version 0.4.0
411 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
412
413 if (fFileBacked)
414 {
415 if (!pwalletdbEncryption->TxnCommit())
416 exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
417
418 delete pwalletdbEncryption;
419 pwalletdbEncryption = NULL;
420 }
421
422 Lock();
423 Unlock(strWalletPassphrase);
424 NewKeyPool();
425 Lock();
426
427 // Need to completely rewrite the wallet file; if we don't, bdb might keep
428 // bits of the unencrypted private key in slack space in the database file.
429 CDB::Rewrite(strWalletFile);
430
431 }
432 NotifyStatusChanged(this);
433
434 return true;
435}
436
437int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
438{
439 AssertLockHeld(cs_wallet); // nOrderPosNext
440 int64_t nRet = nOrderPosNext++;
441 if (pwalletdb) {
442 pwalletdb->WriteOrderPosNext(nOrderPosNext);
443 } else {
444 CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
445 }
446 return nRet;
447}
448
449CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
450{
451 AssertLockHeld(cs_wallet); // mapWallet
452 CWalletDB walletdb(strWalletFile);
453
454 // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
455 TxItems txOrdered;
456
457 // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
458 // would make this much faster for applications that do this a lot.
459 for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
460 {
461 CWalletTx* wtx = &((*it).second);
462 txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
463 }
464 acentries.clear();
465 walletdb.ListAccountCreditDebit(strAccount, acentries);
466 BOOST_FOREACH(CAccountingEntry& entry, acentries)
467 {
468 txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
469 }
470
471 return txOrdered;
472}
473
474void CWallet::MarkDirty()
475{
476 {
477 LOCK(cs_wallet);
478 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
479 item.second.MarkDirty();
480 }
481}
482
483bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
484{
485 uint256 hash = wtxIn.GetHash();
486
487 if (fFromLoadWallet)
488 {
489 mapWallet[hash] = wtxIn;
490 mapWallet[hash].BindWallet(this);
491 AddToSpends(hash);
492 }
493 else
494 {
495 LOCK(cs_wallet);
496 // Inserts only if not already there, returns tx inserted or tx found
497 pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
498 CWalletTx& wtx = (*ret.first).second;
499 wtx.BindWallet(this);
500 bool fInsertedNew = ret.second;
501 if (fInsertedNew)
502 {
503 wtx.nTimeReceived = GetAdjustedTime();
504 wtx.nOrderPos = IncOrderPosNext();
505
506 wtx.nTimeSmart = wtx.nTimeReceived;
507 if (wtxIn.hashBlock != 0)
508 {
509 if (mapBlockIndex.count(wtxIn.hashBlock))
510 {
511 unsigned int latestNow = wtx.nTimeReceived;
512 unsigned int latestEntry = 0;
513 {
514 // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
515 int64_t latestTolerated = latestNow + 300;
516 std::list<CAccountingEntry> acentries;
517 TxItems txOrdered = OrderedTxItems(acentries);
518 for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
519 {
520 CWalletTx *const pwtx = (*it).second.first;
521 if (pwtx == &wtx)
522 continue;
523 CAccountingEntry *const pacentry = (*it).second.second;
524 int64_t nSmartTime;
525 if (pwtx)
526 {
527 nSmartTime = pwtx->nTimeSmart;
528 if (!nSmartTime)
529 nSmartTime = pwtx->nTimeReceived;
530 }
531 else
532 nSmartTime = pacentry->nTime;
533 if (nSmartTime <= latestTolerated)
534 {
535 latestEntry = nSmartTime;
536 if (nSmartTime > latestNow)
537 latestNow = nSmartTime;
538 break;
539 }
540 }
541 }
542
543 unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
544 wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
545 }
546 else
547 LogPrintf("AddToWallet() : found %s in block %s not in index\n",
548 wtxIn.GetHash().ToString(),
549 wtxIn.hashBlock.ToString());
550 }
551 AddToSpends(hash);
552 }
553
554 bool fUpdated = false;
555 if (!fInsertedNew)
556 {
557 // Merge
558 if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
559 {
560 wtx.hashBlock = wtxIn.hashBlock;
561 fUpdated = true;
562 }
563 if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
564 {
565 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
566 wtx.nIndex = wtxIn.nIndex;
567 fUpdated = true;
568 }
569 if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
570 {
571 wtx.fFromMe = wtxIn.fFromMe;
572 fUpdated = true;
573 }
574 }
575
576 //// debug print
577 LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
578
579 // Write to disk
580 if (fInsertedNew || fUpdated)
581 if (!wtx.WriteToDisk())
582 return false;
583
584 // Break debit/credit balance caches:
585 wtx.MarkDirty();
586
587 // Notify UI of new or updated transaction
588 NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
589
590 // notify an external script when a wallet transaction comes in or is updated
591 std::string strCmd = GetArg("-walletnotify", "");
592
593 if ( !strCmd.empty())
594 {
595 boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
596 boost::thread t(runCommand, strCmd); // thread runs free
597 }
598
599 }
600 return true;
601}
602
603// Add a transaction to the wallet, or update it.
604// pblock is optional, but should be provided if the transaction is known to be in a block.
605// If fUpdate is true, existing transactions will be updated.
606bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
607{
608 {
609 AssertLockHeld(cs_wallet);
610 bool fExisted = mapWallet.count(hash);
611 if (fExisted && !fUpdate) return false;
612 if (fExisted || IsMine(tx) || IsFromMe(tx))
613 {
614 CWalletTx wtx(this,tx);
615 // Get merkle branch if transaction was found in a block
616 if (pblock)
617 wtx.SetMerkleBranch(pblock);
618 return AddToWallet(wtx);
619 }
620 }
621 return false;
622}
623
624void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock)
625{
626 LOCK2(cs_main, cs_wallet);
627 if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
628 return; // Not one of ours
629
630 // If a transaction changes 'conflicted' state, that changes the balance
631 // available of the outputs it spends. So force those to be
632 // recomputed, also:
633 BOOST_FOREACH(const CTxIn& txin, tx.vin)
634 {
635 if (mapWallet.count(txin.prevout.hash))
636 mapWallet[txin.prevout.hash].MarkDirty();
637 }
638}
639
640void CWallet::EraseFromWallet(const uint256 &hash)
641{
642 if (!fFileBacked)
643 return;
644 {
645 LOCK(cs_wallet);
646 if (mapWallet.erase(hash))
647 CWalletDB(strWalletFile).EraseTx(hash);
648 }
649 return;
650}
651
652
653bool CWallet::IsMine(const CTxIn &txin) const
654{
655 {
656 LOCK(cs_wallet);
657 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
658 if (mi != mapWallet.end())
659 {
660 const CWalletTx& prev = (*mi).second;
661 if (txin.prevout.n < prev.vout.size())
662 if (IsMine(prev.vout[txin.prevout.n]))
663 return true;
664 }
665 }
666 return false;
667}
668
669int64_t CWallet::GetDebit(const CTxIn &txin) const
670{
671 {
672 LOCK(cs_wallet);
673 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
674 if (mi != mapWallet.end())
675 {
676 const CWalletTx& prev = (*mi).second;
677 if (txin.prevout.n < prev.vout.size())
678 if (IsMine(prev.vout[txin.prevout.n]))
679 return prev.vout[txin.prevout.n].nValue;
680 }
681 }
682 return 0;
683}
684
685bool CWallet::IsChange(const CTxOut& txout) const
686{
687 CTxDestination address;
688
689 // TODO: fix handling of 'change' outputs. The assumption is that any
690 // payment to a TX_PUBKEYHASH that is mine but isn't in the address book
691 // is change. That assumption is likely to break when we implement multisignature
692 // wallets that return change back into a multi-signature-protected address;
693 // a better way of identifying which outputs are 'the send' and which are
694 // 'the change' will need to be implemented (maybe extend CWalletTx to remember
695 // which output, if any, was change).
696 if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
697 {
698 LOCK(cs_wallet);
699 if (!mapAddressBook.count(address))
700 return true;
701 }
702 return false;
703}
704
705int64_t CWalletTx::GetTxTime() const
706{
707 int64_t n = nTimeSmart;
708 return n ? n : nTimeReceived;
709}
710
711int CWalletTx::GetRequestCount() const
712{
713 // Returns -1 if it wasn't being tracked
714 int nRequests = -1;
715 {
716 LOCK(pwallet->cs_wallet);
717 if (IsCoinBase())
718 {
719 // Generated block
720 if (hashBlock != 0)
721 {
722 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
723 if (mi != pwallet->mapRequestCount.end())
724 nRequests = (*mi).second;
725 }
726 }
727 else
728 {
729 // Did anyone request this transaction?
730 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
731 if (mi != pwallet->mapRequestCount.end())
732 {
733 nRequests = (*mi).second;
734
735 // How about the block it's in?
736 if (nRequests == 0 && hashBlock != 0)
737 {
738 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
739 if (mi != pwallet->mapRequestCount.end())
740 nRequests = (*mi).second;
741 else
742 nRequests = 1; // If it's in someone else's block it must have got out
743 }
744 }
745 }
746 }
747 return nRequests;
748}
749
750void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
751 list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount) const
752{
753 nFee = 0;
754 listReceived.clear();
755 listSent.clear();
756 strSentAccount = strFromAccount;
757
758 // Compute fee:
759 int64_t nDebit = GetDebit();
760 if (nDebit > 0) // debit>0 means we signed/sent this transaction
761 {
762 int64_t nValueOut = GetValueOut();
763 nFee = nDebit - nValueOut;
764 }
765
766 // Sent/received.
767 BOOST_FOREACH(const CTxOut& txout, vout)
768 {
769 bool fIsMine;
770 // Only need to handle txouts if AT LEAST one of these is true:
771 // 1) they debit from us (sent)
772 // 2) the output is to us (received)
773 if (nDebit > 0)
774 {
775 // Don't report 'change' txouts
776 if (pwallet->IsChange(txout))
777 continue;
778 fIsMine = pwallet->IsMine(txout);
779 }
780 else if (!(fIsMine = pwallet->IsMine(txout)))
781 continue;
782
783 // In either case, we need to get the destination address
784 CTxDestination address;
785 if (!ExtractDestination(txout.scriptPubKey, address))
786 {
787 LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
788 this->GetHash().ToString());
789 address = CNoDestination();
790 }
791
792 // If we are debited by the transaction, add the output as a "sent" entry
793 if (nDebit > 0)
794 listSent.push_back(make_pair(address, txout.nValue));
795
796 // If we are receiving the output, add it as a "received" entry
797 if (fIsMine)
798 listReceived.push_back(make_pair(address, txout.nValue));
799 }
800
801}
802
803void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
804 int64_t& nSent, int64_t& nFee) const
805{
806 nReceived = nSent = nFee = 0;
807
808 int64_t allFee;
809 string strSentAccount;
810 list<pair<CTxDestination, int64_t> > listReceived;
811 list<pair<CTxDestination, int64_t> > listSent;
812 GetAmounts(listReceived, listSent, allFee, strSentAccount);
813
814 if (strAccount == strSentAccount)
815 {
816 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& s, listSent)
817 nSent += s.second;
818 nFee = allFee;
819 }
820 {
821 LOCK(pwallet->cs_wallet);
822 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived)
823 {
824 if (pwallet->mapAddressBook.count(r.first))
825 {
826 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
827 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
828 nReceived += r.second;
829 }
830 else if (strAccount.empty())
831 {
832 nReceived += r.second;
833 }
834 }
835 }
836}
837
838
839bool CWalletTx::WriteToDisk()
840{
841 return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
842}
843
844// Scan the block chain (starting in pindexStart) for transactions
845// from or to us. If fUpdate is true, found transactions that already
846// exist in the wallet will be updated.
847int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
848{
849 int ret = 0;
850 int64_t nNow = GetTime();
851
852 CBlockIndex* pindex = pindexStart;
853 {
854 LOCK2(cs_main, cs_wallet);
855
856 // no need to read and scan block, if block was created before
857 // our wallet birthday (as adjusted for block time variability)
858 while (pindex && nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200)))
859 pindex = chainActive.Next(pindex);
860
861 ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
862 double dProgressStart = Checkpoints::GuessVerificationProgress(pindex, false);
863 double dProgressTip = Checkpoints::GuessVerificationProgress(chainActive.Tip(), false);
864 while (pindex)
865 {
866 if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
867 ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
868
869 CBlock block;
870 ReadBlockFromDisk(block, pindex);
871 BOOST_FOREACH(CTransaction& tx, block.vtx)
872 {
873 if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
874 ret++;
875 }
876 pindex = chainActive.Next(pindex);
877 if (GetTime() >= nNow + 60) {
878 nNow = GetTime();
879 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex));
880 }
881 }
882 ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
883 }
884 return ret;
885}
886
887void CWallet::ReacceptWalletTransactions()
888{
889 LOCK2(cs_main, cs_wallet);
890 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
891 {
892 const uint256& wtxid = item.first;
893 CWalletTx& wtx = item.second;
894 assert(wtx.GetHash() == wtxid);
895
896 int nDepth = wtx.GetDepthInMainChain();
897
898 if (!wtx.IsCoinBase() && nDepth < 0)
899 {
900 // Try to add to memory pool
901 LOCK(mempool.cs);
902 wtx.AcceptToMemoryPool(false);
903 }
904 }
905}
906
907void CWalletTx::RelayWalletTransaction()
908{
909 if (!IsCoinBase())
910 {
911 if (GetDepthInMainChain() == 0) {
912 uint256 hash = GetHash();
913 LogPrintf("Relaying wtx %s\n", hash.ToString());
914 RelayTransaction((CTransaction)*this, hash);
915 }
916 }
917}
918
919set<uint256> CWalletTx::GetConflicts() const
920{
921 set<uint256> result;
922 if (pwallet != NULL)
923 {
924 uint256 myHash = GetHash();
925 result = pwallet->GetConflicts(myHash);
926 result.erase(myHash);
927 }
928 return result;
929}
930
931void CWallet::ResendWalletTransactions()
932{
933 // Do this infrequently and randomly to avoid giving away
934 // that these are our transactions.
935 if (GetTime() < nNextResend)
936 return;
937 bool fFirst = (nNextResend == 0);
938 nNextResend = GetTime() + GetRand(30 * 60);
939 if (fFirst)
940 return;
941
942 // Only do it if there's been a new block since last time
943 if (nTimeBestReceived < nLastResend)
944 return;
945 nLastResend = GetTime();
946
947 // Rebroadcast any of our txes that aren't in a block yet
948 LogPrintf("ResendWalletTransactions()\n");
949 {
950 LOCK(cs_wallet);
951 // Sort them in chronological order
952 multimap<unsigned int, CWalletTx*> mapSorted;
953 BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
954 {
955 CWalletTx& wtx = item.second;
956 // Don't rebroadcast until it's had plenty of time that
957 // it should have gotten in already by now.
958 if (nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60)
959 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
960 }
961 BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
962 {
963 CWalletTx& wtx = *item.second;
964 wtx.RelayWalletTransaction();
965 }
966 }
967}
968
969
970
971
972
973
974//////////////////////////////////////////////////////////////////////////////
975//
976// Actions
977//
978
979
980int64_t CWallet::GetBalance() const
981{
982 int64_t nTotal = 0;
983 {
984 LOCK2(cs_main, cs_wallet);
985 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
986 {
987 const CWalletTx* pcoin = &(*it).second;
988 if (pcoin->IsTrusted())
989 nTotal += pcoin->GetAvailableCredit();
990 }
991 }
992
993 return nTotal;
994}
995
996int64_t CWallet::GetUnconfirmedBalance() const
997{
998 int64_t nTotal = 0;
999 {
1000 LOCK2(cs_main, cs_wallet);
1001 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1002 {
1003 const CWalletTx* pcoin = &(*it).second;
1004 if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
1005 nTotal += pcoin->GetAvailableCredit();
1006 }
1007 }
1008 return nTotal;
1009}
1010
1011int64_t CWallet::GetImmatureBalance() const
1012{
1013 int64_t nTotal = 0;
1014 {
1015 LOCK2(cs_main, cs_wallet);
1016 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1017 {
1018 const CWalletTx* pcoin = &(*it).second;
1019 nTotal += pcoin->GetImmatureCredit();
1020 }
1021 }
1022 return nTotal;
1023}
1024
1025// populate vCoins with vector of spendable COutputs
1026void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
1027{
1028 vCoins.clear();
1029
1030 {
1031 LOCK2(cs_main, cs_wallet);
1032 for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1033 {
1034 const uint256& wtxid = it->first;
1035 const CWalletTx* pcoin = &(*it).second;
1036
1037 if (!IsFinalTx(*pcoin))
1038 continue;
1039
1040 if (fOnlyConfirmed && !pcoin->IsTrusted())
1041 continue;
1042
1043 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1044 continue;
1045
1046 int nDepth = pcoin->GetDepthInMainChain();
1047 if (nDepth < 0)
1048 continue;
1049
1050 for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
1051 if (!(IsSpent(wtxid, i)) && IsMine(pcoin->vout[i]) &&
1052 !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 &&
1053 (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
1054 vCoins.push_back(COutput(pcoin, i, nDepth));
1055 }
1056 }
1057 }
1058}
1059
1060static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > >vValue, int64_t nTotalLower, int64_t nTargetValue,
1061 vector<char>& vfBest, int64_t& nBest, int iterations = 1000)
1062{
1063 vector<char> vfIncluded;
1064
1065 vfBest.assign(vValue.size(), true);
1066 nBest = nTotalLower;
1067
1068 seed_insecure_rand();
1069
1070 for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
1071 {
1072 vfIncluded.assign(vValue.size(), false);
1073 int64_t nTotal = 0;
1074 bool fReachedTarget = false;
1075 for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
1076 {
1077 for (unsigned int i = 0; i < vValue.size(); i++)
1078 {
1079 //The solver here uses a randomized algorithm,
1080 //the randomness serves no real security purpose but is just
1081 //needed to prevent degenerate behavior and it is important
1082 //that the rng fast. We do not use a constant random sequence,
1083 //because there may be some privacy improvement by making
1084 //the selection random.
1085 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
1086 {
1087 nTotal += vValue[i].first;
1088 vfIncluded[i] = true;
1089 if (nTotal >= nTargetValue)
1090 {
1091 fReachedTarget = true;
1092 if (nTotal < nBest)
1093 {
1094 nBest = nTotal;
1095 vfBest = vfIncluded;
1096 }
1097 nTotal -= vValue[i].first;
1098 vfIncluded[i] = false;
1099 }
1100 }
1101 }
1102 }
1103 }
1104}
1105
1106bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
1107 set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const
1108{
1109 setCoinsRet.clear();
1110 nValueRet = 0;
1111
1112 // List of values less than target
1113 pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
1114 coinLowestLarger.first = std::numeric_limits<int64_t>::max();
1115 coinLowestLarger.second.first = NULL;
1116 vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue;
1117 int64_t nTotalLower = 0;
1118
1119 random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
1120
1121 BOOST_FOREACH(COutput output, vCoins)
1122 {
1123 const CWalletTx *pcoin = output.tx;
1124
1125 if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
1126 continue;
1127
1128 int i = output.i;
1129 int64_t n = pcoin->vout[i].nValue;
1130
1131 pair<int64_t,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1132
1133 if (n == nTargetValue)
1134 {
1135 setCoinsRet.insert(coin.second);
1136 nValueRet += coin.first;
1137 return true;
1138 }
1139 else if (n < nTargetValue + CENT)
1140 {
1141 vValue.push_back(coin);
1142 nTotalLower += n;
1143 }
1144 else if (n < coinLowestLarger.first)
1145 {
1146 coinLowestLarger = coin;
1147 }
1148 }
1149
1150 if (nTotalLower == nTargetValue)
1151 {
1152 for (unsigned int i = 0; i < vValue.size(); ++i)
1153 {
1154 setCoinsRet.insert(vValue[i].second);
1155 nValueRet += vValue[i].first;
1156 }
1157 return true;
1158 }
1159
1160 if (nTotalLower < nTargetValue)
1161 {
1162 if (coinLowestLarger.second.first == NULL)
1163 return false;
1164 setCoinsRet.insert(coinLowestLarger.second);
1165 nValueRet += coinLowestLarger.first;
1166 return true;
1167 }
1168
1169 // Solve subset sum by stochastic approximation
1170 sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1171 vector<char> vfBest;
1172 int64_t nBest;
1173
1174 ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
1175 if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
1176 ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1177
1178 // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
1179 // or the next bigger coin is closer), return the bigger coin
1180 if (coinLowestLarger.second.first &&
1181 ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
1182 {
1183 setCoinsRet.insert(coinLowestLarger.second);
1184 nValueRet += coinLowestLarger.first;
1185 }
1186 else {
1187 for (unsigned int i = 0; i < vValue.size(); i++)
1188 if (vfBest[i])
1189 {
1190 setCoinsRet.insert(vValue[i].second);
1191 nValueRet += vValue[i].first;
1192 }
1193
1194 LogPrint("selectcoins", "SelectCoins() best subset: ");
1195 for (unsigned int i = 0; i < vValue.size(); i++)
1196 if (vfBest[i])
1197 LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first));
1198 LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
1199 }
1200
1201 return true;
1202}
1203
1204bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const
1205{
1206 vector<COutput> vCoins;
1207 AvailableCoins(vCoins, true, coinControl);
1208
1209 // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
1210 if (coinControl && coinControl->HasSelected())
1211 {
1212 BOOST_FOREACH(const COutput& out, vCoins)
1213 {
1214 nValueRet += out.tx->vout[out.i].nValue;
1215 setCoinsRet.insert(make_pair(out.tx, out.i));
1216 }
1217 return (nValueRet >= nTargetValue);
1218 }
1219
1220 return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
1221 SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
1222 (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet)));
1223}
1224
1225
1226
1227
1228bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
1229 CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1230{
1231 int64_t nValue = 0;
1232 BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1233 {
1234 if (nValue < 0)
1235 {
1236 strFailReason = _("Transaction amounts must be positive");
1237 return false;
1238 }
1239 nValue += s.second;
1240 }
1241 if (vecSend.empty() || nValue < 0)
1242 {
1243 strFailReason = _("Transaction amounts must be positive");
1244 return false;
1245 }
1246
1247 wtxNew.BindWallet(this);
1248
1249 {
1250 LOCK2(cs_main, cs_wallet);
1251 {
1252 nFeeRet = payTxFee.GetFeePerK();
1253 while (true)
1254 {
1255 wtxNew.vin.clear();
1256 wtxNew.vout.clear();
1257 wtxNew.fFromMe = true;
1258
1259 int64_t nTotalValue = nValue + nFeeRet;
1260 double dPriority = 0;
1261 // vouts to the payees
1262 BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
1263 {
1264 CTxOut txout(s.second, s.first);
1265 if (txout.IsDust(CTransaction::minRelayTxFee))
1266 {
1267 strFailReason = _("Transaction amount too small");
1268 return false;
1269 }
1270 wtxNew.vout.push_back(txout);
1271 }
1272
1273 // Choose coins to use
1274 set<pair<const CWalletTx*,unsigned int> > setCoins;
1275 int64_t nValueIn = 0;
1276 if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
1277 {
1278 strFailReason = _("Insufficient funds");
1279 return false;
1280 }
1281 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1282 {
1283 int64_t nCredit = pcoin.first->vout[pcoin.second].nValue;
1284 //The priority after the next block (depth+1) is used instead of the current,
1285 //reflecting an assumption the user would accept a bit more delay for
1286 //a chance at a free transaction.
1287 dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1);
1288 }
1289
1290 int64_t nChange = nValueIn - nValue - nFeeRet;
1291
1292 if (nChange > 0)
1293 {
1294 // Fill a vout to ourself
1295 // TODO: pass in scriptChange instead of reservekey so
1296 // change transaction isn't always pay-to-bitcoin-address
1297 CScript scriptChange;
1298
1299 // coin control: send change to custom address
1300 if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
1301 scriptChange.SetDestination(coinControl->destChange);
1302
1303 // no coin control: send change to newly generated address
1304 else
1305 {
1306 // Note: We use a new key here to keep it from being obvious which side is the change.
1307 // The drawback is that by not reusing a previous key, the change may be lost if a
1308 // backup is restored, if the backup doesn't have the new private key for the change.
1309 // If we reused the old key, it would be possible to add code to look for and
1310 // rediscover unknown transactions that were written with keys of ours to recover
1311 // post-backup change.
1312
1313 // Reserve a new key pair from key pool
1314 CPubKey vchPubKey;
1315 bool ret;
1316 ret = reservekey.GetReservedKey(vchPubKey);
1317 assert(ret); // should never fail, as we just unlocked
1318
1319 scriptChange.SetDestination(vchPubKey.GetID());
1320 }
1321
1322 CTxOut newTxOut(nChange, scriptChange);
1323
1324 // Never create dust outputs; if we would, just
1325 // add the dust to the fee.
1326 if (newTxOut.IsDust(CTransaction::minRelayTxFee))
1327 {
1328 nFeeRet += nChange;
1329 reservekey.ReturnKey();
1330 }
1331 else
1332 {
1333 // Insert change txn at random position:
1334 vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
1335 wtxNew.vout.insert(position, newTxOut);
1336 }
1337 }
1338 else
1339 reservekey.ReturnKey();
1340
1341 // Fill vin
1342 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1343 wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1344
1345 // Sign
1346 int nIn = 0;
1347 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1348 if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1349 {
1350 strFailReason = _("Signing transaction failed");
1351 return false;
1352 }
1353
1354 // Limit size
1355 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1356 if (nBytes >= MAX_STANDARD_TX_SIZE)
1357 {
1358 strFailReason = _("Transaction too large");
1359 return false;
1360 }
1361 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
1362
1363 // Check that enough fee is included
1364 int64_t nPayFee = payTxFee.GetFee(nBytes);
1365 bool fAllowFree = AllowFree(dPriority);
1366 int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND);
1367 if (nFeeRet < max(nPayFee, nMinFee))
1368 {
1369 nFeeRet = max(nPayFee, nMinFee);
1370 continue;
1371 }
1372
1373 wtxNew.fTimeReceivedIsTxTime = true;
1374
1375 break;
1376 }
1377 }
1378 }
1379 return true;
1380}
1381
1382bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue,
1383 CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
1384{
1385 vector< pair<CScript, int64_t> > vecSend;
1386 vecSend.push_back(make_pair(scriptPubKey, nValue));
1387 return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
1388}
1389
1390// Call after CreateTransaction unless you want to abort
1391bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1392{
1393 {
1394 LOCK2(cs_main, cs_wallet);
1395 LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
1396 {
1397 // This is only to keep the database open to defeat the auto-flush for the
1398 // duration of this scope. This is the only place where this optimization
1399 // maybe makes sense; please don't do it anywhere else.
1400 CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1401
1402 // Take key pair from key pool so it won't be used again
1403 reservekey.KeepKey();
1404
1405 // Add tx to wallet, because if it has change it's also ours,
1406 // otherwise just for transaction history.
1407 AddToWallet(wtxNew);
1408
1409 // Notify that old coins are spent
1410 set<CWalletTx*> setCoins;
1411 BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1412 {
1413 CWalletTx &coin = mapWallet[txin.prevout.hash];
1414 coin.BindWallet(this);
1415 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1416 }
1417
1418 if (fFileBacked)
1419 delete pwalletdb;
1420 }
1421
1422 // Track how many getdata requests our transaction gets
1423 mapRequestCount[wtxNew.GetHash()] = 0;
1424
1425 // Broadcast
1426 if (!wtxNew.AcceptToMemoryPool(false))
1427 {
1428 // This must not fail. The transaction has already been signed and recorded.
1429 LogPrintf("CommitTransaction() : Error: Transaction not valid");
1430 return false;
1431 }
1432 wtxNew.RelayWalletTransaction();
1433 }
1434 return true;
1435}
1436
1437
1438
1439
1440string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew)
1441{
1442 CReserveKey reservekey(this);
1443 int64_t nFeeRequired;
1444
1445 if (IsLocked())
1446 {
1447 string strError = _("Error: Wallet locked, unable to create transaction!");
1448 LogPrintf("SendMoney() : %s", strError);
1449 return strError;
1450 }
1451 string strError;
1452 if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
1453 {
1454 if (nValue + nFeeRequired > GetBalance())
1455 strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired));
1456 LogPrintf("SendMoney() : %s\n", strError);
1457 return strError;
1458 }
1459
1460 if (!CommitTransaction(wtxNew, reservekey))
1461 return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
1462
1463 return "";
1464}
1465
1466
1467
1468string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew)
1469{
1470 // Check amount
1471 if (nValue <= 0)
1472 return _("Invalid amount");
1473 if (nValue > GetBalance())
1474 return _("Insufficient funds");
1475
1476 // Parse Bitcoin address
1477 CScript scriptPubKey;
1478 scriptPubKey.SetDestination(address);
1479
1480 return SendMoney(scriptPubKey, nValue, wtxNew);
1481}
1482
1483
1484
1485
1486DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1487{
1488 if (!fFileBacked)
1489 return DB_LOAD_OK;
1490 fFirstRunRet = false;
1491 DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1492 if (nLoadWalletRet == DB_NEED_REWRITE)
1493 {
1494 if (CDB::Rewrite(strWalletFile, "\x04pool"))
1495 {
1496 LOCK(cs_wallet);
1497 setKeyPool.clear();
1498 // Note: can't top-up keypool here, because wallet is locked.
1499 // User will be prompted to unlock wallet the next operation
1500 // the requires a new key.
1501 }
1502 }
1503
1504 if (nLoadWalletRet != DB_LOAD_OK)
1505 return nLoadWalletRet;
1506 fFirstRunRet = !vchDefaultKey.IsValid();
1507
1508 uiInterface.LoadWallet(this);
1509
1510 return DB_LOAD_OK;
1511}
1512
1513
1514DBErrors CWallet::ZapWalletTx()
1515{
1516 if (!fFileBacked)
1517 return DB_LOAD_OK;
1518 DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this);
1519 if (nZapWalletTxRet == DB_NEED_REWRITE)
1520 {
1521 if (CDB::Rewrite(strWalletFile, "\x04pool"))
1522 {
1523 LOCK(cs_wallet);
1524 setKeyPool.clear();
1525 // Note: can't top-up keypool here, because wallet is locked.
1526 // User will be prompted to unlock wallet the next operation
1527 // the requires a new key.
1528 }
1529 }
1530
1531 if (nZapWalletTxRet != DB_LOAD_OK)
1532 return nZapWalletTxRet;
1533
1534 return DB_LOAD_OK;
1535}
1536
1537
1538bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
1539{
1540 bool fUpdated = false;
1541 {
1542 LOCK(cs_wallet); // mapAddressBook
1543 std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
1544 fUpdated = mi != mapAddressBook.end();
1545 mapAddressBook[address].name = strName;
1546 if (!strPurpose.empty()) /* update purpose only if requested */
1547 mapAddressBook[address].purpose = strPurpose;
1548 }
1549 NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
1550 strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
1551 if (!fFileBacked)
1552 return false;
1553 if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
1554 return false;
1555 return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1556}
1557
1558bool CWallet::DelAddressBook(const CTxDestination& address)
1559{
1560 {
1561 LOCK(cs_wallet); // mapAddressBook
1562
1563 if(fFileBacked)
1564 {
1565 // Delete destdata tuples associated with address
1566 std::string strAddress = CBitcoinAddress(address).ToString();
1567 BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
1568 {
1569 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
1570 }
1571 }
1572 mapAddressBook.erase(address);
1573 }
1574
1575 NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
1576
1577 if (!fFileBacked)
1578 return false;
1579 CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
1580 return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1581}
1582
1583bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1584{
1585 if (fFileBacked)
1586 {
1587 if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1588 return false;
1589 }
1590 vchDefaultKey = vchPubKey;
1591 return true;
1592}
1593
1594//
1595// Mark old keypool keys as used,
1596// and generate all new keys
1597//
1598bool CWallet::NewKeyPool()
1599{
1600 {
1601 LOCK(cs_wallet);
1602 CWalletDB walletdb(strWalletFile);
1603 BOOST_FOREACH(int64_t nIndex, setKeyPool)
1604 walletdb.ErasePool(nIndex);
1605 setKeyPool.clear();
1606
1607 if (IsLocked())
1608 return false;
1609
1610 int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
1611 for (int i = 0; i < nKeys; i++)
1612 {
1613 int64_t nIndex = i+1;
1614 walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1615 setKeyPool.insert(nIndex);
1616 }
1617 LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
1618 }
1619 return true;
1620}
1621
1622bool CWallet::TopUpKeyPool(unsigned int kpSize)
1623{
1624 {
1625 LOCK(cs_wallet);
1626
1627 if (IsLocked())
1628 return false;
1629
1630 CWalletDB walletdb(strWalletFile);
1631
1632 // Top up key pool
1633 unsigned int nTargetSize;
1634 if (kpSize > 0)
1635 nTargetSize = kpSize;
1636 else
1637 nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
1638
1639 while (setKeyPool.size() < (nTargetSize + 1))
1640 {
1641 int64_t nEnd = 1;
1642 if (!setKeyPool.empty())
1643 nEnd = *(--setKeyPool.end()) + 1;
1644 if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1645 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1646 setKeyPool.insert(nEnd);
1647 LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
1648 }
1649 }
1650 return true;
1651}
1652
1653void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
1654{
1655 nIndex = -1;
1656 keypool.vchPubKey = CPubKey();
1657 {
1658 LOCK(cs_wallet);
1659
1660 if (!IsLocked())
1661 TopUpKeyPool();
1662
1663 // Get the oldest key
1664 if(setKeyPool.empty())
1665 return;
1666
1667 CWalletDB walletdb(strWalletFile);
1668
1669 nIndex = *(setKeyPool.begin());
1670 setKeyPool.erase(setKeyPool.begin());
1671 if (!walletdb.ReadPool(nIndex, keypool))
1672 throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1673 if (!HaveKey(keypool.vchPubKey.GetID()))
1674 throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1675 assert(keypool.vchPubKey.IsValid());
1676 LogPrintf("keypool reserve %d\n", nIndex);
1677 }
1678}
1679
1680void CWallet::KeepKey(int64_t nIndex)
1681{
1682 // Remove from key pool
1683 if (fFileBacked)
1684 {
1685 CWalletDB walletdb(strWalletFile);
1686 walletdb.ErasePool(nIndex);
1687 }
1688 LogPrintf("keypool keep %d\n", nIndex);
1689}
1690
1691void CWallet::ReturnKey(int64_t nIndex)
1692{
1693 // Return to key pool
1694 {
1695 LOCK(cs_wallet);
1696 setKeyPool.insert(nIndex);
1697 }
1698 LogPrintf("keypool return %d\n", nIndex);
1699}
1700
1701bool CWallet::GetKeyFromPool(CPubKey& result)
1702{
1703 int64_t nIndex = 0;
1704 CKeyPool keypool;
1705 {
1706 LOCK(cs_wallet);
1707 ReserveKeyFromKeyPool(nIndex, keypool);
1708 if (nIndex == -1)
1709 {
1710 if (IsLocked()) return false;
1711 result = GenerateNewKey();
1712 return true;
1713 }
1714 KeepKey(nIndex);
1715 result = keypool.vchPubKey;
1716 }
1717 return true;
1718}
1719
1720int64_t CWallet::GetOldestKeyPoolTime()
1721{
1722 int64_t nIndex = 0;
1723 CKeyPool keypool;
1724 ReserveKeyFromKeyPool(nIndex, keypool);
1725 if (nIndex == -1)
1726 return GetTime();
1727 ReturnKey(nIndex);
1728 return keypool.nTime;
1729}
1730
1731std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
1732{
1733 map<CTxDestination, int64_t> balances;
1734
1735 {
1736 LOCK(cs_wallet);
1737 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1738 {
1739 CWalletTx *pcoin = &walletEntry.second;
1740
1741 if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted())
1742 continue;
1743
1744 if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1745 continue;
1746
1747 int nDepth = pcoin->GetDepthInMainChain();
1748 if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
1749 continue;
1750
1751 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1752 {
1753 CTxDestination addr;
1754 if (!IsMine(pcoin->vout[i]))
1755 continue;
1756 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
1757 continue;
1758
1759 int64_t n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
1760
1761 if (!balances.count(addr))
1762 balances[addr] = 0;
1763 balances[addr] += n;
1764 }
1765 }
1766 }
1767
1768 return balances;
1769}
1770
1771set< set<CTxDestination> > CWallet::GetAddressGroupings()
1772{
1773 AssertLockHeld(cs_wallet); // mapWallet
1774 set< set<CTxDestination> > groupings;
1775 set<CTxDestination> grouping;
1776
1777 BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1778 {
1779 CWalletTx *pcoin = &walletEntry.second;
1780
1781 if (pcoin->vin.size() > 0)
1782 {
1783 bool any_mine = false;
1784 // group all input addresses with each other
1785 BOOST_FOREACH(CTxIn txin, pcoin->vin)
1786 {
1787 CTxDestination address;
1788 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
1789 continue;
1790 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
1791 continue;
1792 grouping.insert(address);
1793 any_mine = true;
1794 }
1795
1796 // group change with input addresses
1797 if (any_mine)
1798 {
1799 BOOST_FOREACH(CTxOut txout, pcoin->vout)
1800 if (IsChange(txout))
1801 {
1802 CTxDestination txoutAddr;
1803 if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
1804 continue;
1805 grouping.insert(txoutAddr);
1806 }
1807 }
1808 if (grouping.size() > 0)
1809 {
1810 groupings.insert(grouping);
1811 grouping.clear();
1812 }
1813 }
1814
1815 // group lone addrs by themselves
1816 for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1817 if (IsMine(pcoin->vout[i]))
1818 {
1819 CTxDestination address;
1820 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
1821 continue;
1822 grouping.insert(address);
1823 groupings.insert(grouping);
1824 grouping.clear();
1825 }
1826 }
1827
1828 set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
1829 map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
1830 BOOST_FOREACH(set<CTxDestination> grouping, groupings)
1831 {
1832 // make a set of all the groups hit by this new group
1833 set< set<CTxDestination>* > hits;
1834 map< CTxDestination, set<CTxDestination>* >::iterator it;
1835 BOOST_FOREACH(CTxDestination address, grouping)
1836 if ((it = setmap.find(address)) != setmap.end())
1837 hits.insert((*it).second);
1838
1839 // merge all hit groups into a new single group and delete old groups
1840 set<CTxDestination>* merged = new set<CTxDestination>(grouping);
1841 BOOST_FOREACH(set<CTxDestination>* hit, hits)
1842 {
1843 merged->insert(hit->begin(), hit->end());
1844 uniqueGroupings.erase(hit);
1845 delete hit;
1846 }
1847 uniqueGroupings.insert(merged);
1848
1849 // update setmap
1850 BOOST_FOREACH(CTxDestination element, *merged)
1851 setmap[element] = merged;
1852 }
1853
1854 set< set<CTxDestination> > ret;
1855 BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
1856 {
1857 ret.insert(*uniqueGrouping);
1858 delete uniqueGrouping;
1859 }
1860
1861 return ret;
1862}
1863
1864set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
1865{
1866 AssertLockHeld(cs_wallet); // mapWallet
1867 set<CTxDestination> result;
1868 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
1869 {
1870 const CTxDestination& address = item.first;
1871 const string& strName = item.second.name;
1872 if (strName == strAccount)
1873 result.insert(address);
1874 }
1875 return result;
1876}
1877
1878bool CReserveKey::GetReservedKey(CPubKey& pubkey)
1879{
1880 if (nIndex == -1)
1881 {
1882 CKeyPool keypool;
1883 pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1884 if (nIndex != -1)
1885 vchPubKey = keypool.vchPubKey;
1886 else {
1887 if (pwallet->vchDefaultKey.IsValid()) {
1888 LogPrintf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1889 vchPubKey = pwallet->vchDefaultKey;
1890 } else
1891 return false;
1892 }
1893 }
1894 assert(vchPubKey.IsValid());
1895 pubkey = vchPubKey;
1896 return true;
1897}
1898
1899void CReserveKey::KeepKey()
1900{
1901 if (nIndex != -1)
1902 pwallet->KeepKey(nIndex);
1903 nIndex = -1;
1904 vchPubKey = CPubKey();
1905}
1906
1907void CReserveKey::ReturnKey()
1908{
1909 if (nIndex != -1)
1910 pwallet->ReturnKey(nIndex);
1911 nIndex = -1;
1912 vchPubKey = CPubKey();
1913}
1914
1915void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
1916{
1917 setAddress.clear();
1918
1919 CWalletDB walletdb(strWalletFile);
1920
1921 LOCK2(cs_main, cs_wallet);
1922 BOOST_FOREACH(const int64_t& id, setKeyPool)
1923 {
1924 CKeyPool keypool;
1925 if (!walletdb.ReadPool(id, keypool))
1926 throw runtime_error("GetAllReserveKeyHashes() : read failed");
1927 assert(keypool.vchPubKey.IsValid());
1928 CKeyID keyID = keypool.vchPubKey.GetID();
1929 if (!HaveKey(keyID))
1930 throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1931 setAddress.insert(keyID);
1932 }
1933}
1934
1935void CWallet::UpdatedTransaction(const uint256 &hashTx)
1936{
1937 {
1938 LOCK(cs_wallet);
1939 // Only notify UI if this transaction is in this wallet
1940 map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
1941 if (mi != mapWallet.end())
1942 NotifyTransactionChanged(this, hashTx, CT_UPDATED);
1943 }
1944}
1945
1946void CWallet::LockCoin(COutPoint& output)
1947{
1948 AssertLockHeld(cs_wallet); // setLockedCoins
1949 setLockedCoins.insert(output);
1950}
1951
1952void CWallet::UnlockCoin(COutPoint& output)
1953{
1954 AssertLockHeld(cs_wallet); // setLockedCoins
1955 setLockedCoins.erase(output);
1956}
1957
1958void CWallet::UnlockAllCoins()
1959{
1960 AssertLockHeld(cs_wallet); // setLockedCoins
1961 setLockedCoins.clear();
1962}
1963
1964bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
1965{
1966 AssertLockHeld(cs_wallet); // setLockedCoins
1967 COutPoint outpt(hash, n);
1968
1969 return (setLockedCoins.count(outpt) > 0);
1970}
1971
1972void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
1973{
1974 AssertLockHeld(cs_wallet); // setLockedCoins
1975 for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
1976 it != setLockedCoins.end(); it++) {
1977 COutPoint outpt = (*it);
1978 vOutpts.push_back(outpt);
1979 }
1980}
1981
1982void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
1983 AssertLockHeld(cs_wallet); // mapKeyMetadata
1984 mapKeyBirth.clear();
1985
1986 // get birth times for keys with metadata
1987 for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
1988 if (it->second.nCreateTime)
1989 mapKeyBirth[it->first] = it->second.nCreateTime;
1990
1991 // map in which we'll infer heights of other keys
1992 CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
1993 std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
1994 std::set<CKeyID> setKeys;
1995 GetKeys(setKeys);
1996 BOOST_FOREACH(const CKeyID &keyid, setKeys) {
1997 if (mapKeyBirth.count(keyid) == 0)
1998 mapKeyFirstBlock[keyid] = pindexMax;
1999 }
2000 setKeys.clear();
2001
2002 // if there are no such keys, we're done
2003 if (mapKeyFirstBlock.empty())
2004 return;
2005
2006 // find first block that affects those keys, if there are any left
2007 std::vector<CKeyID> vAffected;
2008 for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
2009 // iterate over all wallet transactions...
2010 const CWalletTx &wtx = (*it).second;
2011 std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
2012 if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
2013 // ... which are already in a block
2014 int nHeight = blit->second->nHeight;
2015 BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
2016 // iterate over all their outputs
2017 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
2018 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
2019 // ... and all their affected keys
2020 std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
2021 if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
2022 rit->second = blit->second;
2023 }
2024 vAffected.clear();
2025 }
2026 }
2027 }
2028
2029 // Extract block timestamps for those keys
2030 for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
2031 mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
2032}
2033
2034bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
2035{
2036 if (boost::get<CNoDestination>(&dest))
2037 return false;
2038
2039 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
2040 if (!fFileBacked)
2041 return true;
2042 return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
2043}
2044
2045bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
2046{
2047 if (!mapAddressBook[dest].destdata.erase(key))
2048 return false;
2049 if (!fFileBacked)
2050 return true;
2051 return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
2052}
2053
2054bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
2055{
2056 mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
2057 return true;
2058}
2059
2060bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
2061{
2062 std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
2063 if(i != mapAddressBook.end())
2064 {
2065 CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
2066 if(j != i->second.destdata.end())
2067 {
2068 if(value)
2069 *value = j->second;
2070 return true;
2071 }
2072 }
2073 return false;
2074}
This page took 0.045757 seconds and 4 git commands to generate.