]> Git Repo - VerusCoin.git/blob - src/wallet.cpp
Merge pull request #1916 from jgarzik/caddrdb-bug
[VerusCoin.git] / src / wallet.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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 #include "walletdb.h"
8 #include "crypter.h"
9 #include "ui_interface.h"
10 #include "base58.h"
11
12 using namespace std;
13
14
15 //////////////////////////////////////////////////////////////////////////////
16 //
17 // mapWallet
18 //
19
20 struct CompareValueOnly
21 {
22     bool operator()(const pair<int64, pair<const CWalletTx*, unsigned int> >& t1,
23                     const pair<int64, pair<const CWalletTx*, unsigned int> >& t2) const
24     {
25         return t1.first < t2.first;
26     }
27 };
28
29 CPubKey CWallet::GenerateNewKey()
30 {
31     bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
32
33     RandAddSeedPerfmon();
34     CKey key;
35     key.MakeNewKey(fCompressed);
36
37     // Compressed public keys were introduced in version 0.6.0
38     if (fCompressed)
39         SetMinVersion(FEATURE_COMPRPUBKEY);
40
41     if (!AddKey(key))
42         throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
43     return key.GetPubKey();
44 }
45
46 bool CWallet::AddKey(const CKey& key)
47 {
48     if (!CCryptoKeyStore::AddKey(key))
49         return false;
50     if (!fFileBacked)
51         return true;
52     if (!IsCrypted())
53         return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
54     return true;
55 }
56
57 bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
58 {
59     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
60         return false;
61     if (!fFileBacked)
62         return true;
63     {
64         LOCK(cs_wallet);
65         if (pwalletdbEncryption)
66             return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
67         else
68             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
69     }
70     return false;
71 }
72
73 bool CWallet::AddCScript(const CScript& redeemScript)
74 {
75     if (!CCryptoKeyStore::AddCScript(redeemScript))
76         return false;
77     if (!fFileBacked)
78         return true;
79     return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
80 }
81
82 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
83 {
84     if (!IsLocked())
85         return false;
86
87     CCrypter crypter;
88     CKeyingMaterial vMasterKey;
89
90     {
91         LOCK(cs_wallet);
92         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
93         {
94             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
95                 return false;
96             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
97                 return false;
98             if (CCryptoKeyStore::Unlock(vMasterKey))
99                 return true;
100         }
101     }
102     return false;
103 }
104
105 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
106 {
107     bool fWasLocked = IsLocked();
108
109     {
110         LOCK(cs_wallet);
111         Lock();
112
113         CCrypter crypter;
114         CKeyingMaterial vMasterKey;
115         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
116         {
117             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
118                 return false;
119             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
120                 return false;
121             if (CCryptoKeyStore::Unlock(vMasterKey))
122             {
123                 int64 nStartTime = GetTimeMillis();
124                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
125                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
126
127                 nStartTime = GetTimeMillis();
128                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
129                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
130
131                 if (pMasterKey.second.nDeriveIterations < 25000)
132                     pMasterKey.second.nDeriveIterations = 25000;
133
134                 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
135
136                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
137                     return false;
138                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
139                     return false;
140                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
141                 if (fWasLocked)
142                     Lock();
143                 return true;
144             }
145         }
146     }
147
148     return false;
149 }
150
151 void CWallet::SetBestChain(const CBlockLocator& loc)
152 {
153     CWalletDB walletdb(strWalletFile);
154     walletdb.WriteBestBlock(loc);
155 }
156
157 // This class implements an addrIncoming entry that causes pre-0.4
158 // clients to crash on startup if reading a private-key-encrypted wallet.
159 class CCorruptAddress
160 {
161 public:
162     IMPLEMENT_SERIALIZE
163     (
164         if (nType & SER_DISK)
165             READWRITE(nVersion);
166     )
167 };
168
169 bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
170 {
171     if (nWalletVersion >= nVersion)
172         return true;
173
174     // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
175     if (fExplicit && nVersion > nWalletMaxVersion)
176             nVersion = FEATURE_LATEST;
177
178     nWalletVersion = nVersion;
179
180     if (nVersion > nWalletMaxVersion)
181         nWalletMaxVersion = nVersion;
182
183     if (fFileBacked)
184     {
185         CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
186         if (nWalletVersion >= 40000)
187         {
188             // Versions prior to 0.4.0 did not support the "minversion" record.
189             // Use a CCorruptAddress to make them crash instead.
190             CCorruptAddress corruptAddress;
191             pwalletdb->WriteSetting("addrIncoming", corruptAddress);
192         }
193         if (nWalletVersion > 40000)
194             pwalletdb->WriteMinVersion(nWalletVersion);
195         if (!pwalletdbIn)
196             delete pwalletdb;
197     }
198
199     return true;
200 }
201
202 bool CWallet::SetMaxVersion(int nVersion)
203 {
204     // cannot downgrade below current version
205     if (nWalletVersion > nVersion)
206         return false;
207
208     nWalletMaxVersion = nVersion;
209
210     return true;
211 }
212
213 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
214 {
215     if (IsCrypted())
216         return false;
217
218     CKeyingMaterial vMasterKey;
219     RandAddSeedPerfmon();
220
221     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
222     RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
223
224     CMasterKey kMasterKey;
225
226     RandAddSeedPerfmon();
227     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
228     RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
229
230     CCrypter crypter;
231     int64 nStartTime = GetTimeMillis();
232     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
233     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
234
235     nStartTime = GetTimeMillis();
236     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
237     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
238
239     if (kMasterKey.nDeriveIterations < 25000)
240         kMasterKey.nDeriveIterations = 25000;
241
242     printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
243
244     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
245         return false;
246     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
247         return false;
248
249     {
250         LOCK(cs_wallet);
251         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
252         if (fFileBacked)
253         {
254             pwalletdbEncryption = new CWalletDB(strWalletFile);
255             if (!pwalletdbEncryption->TxnBegin())
256                 return false;
257             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
258         }
259
260         if (!EncryptKeys(vMasterKey))
261         {
262             if (fFileBacked)
263                 pwalletdbEncryption->TxnAbort();
264             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.
265         }
266
267         // Encryption was introduced in version 0.4.0
268         SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
269
270         if (fFileBacked)
271         {
272             if (!pwalletdbEncryption->TxnCommit())
273                 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.
274
275             delete pwalletdbEncryption;
276             pwalletdbEncryption = NULL;
277         }
278
279         Lock();
280         Unlock(strWalletPassphrase);
281         NewKeyPool();
282         Lock();
283
284         // Need to completely rewrite the wallet file; if we don't, bdb might keep
285         // bits of the unencrypted private key in slack space in the database file.
286         CDB::Rewrite(strWalletFile);
287
288     }
289     NotifyStatusChanged(this);
290
291     return true;
292 }
293
294 int64 CWallet::IncOrderPosNext()
295 {
296     int64 nRet = nOrderPosNext;
297     CWalletDB(strWalletFile).WriteOrderPosNext(++nOrderPosNext);
298     return nRet;
299 }
300
301 CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
302 {
303     CWalletDB walletdb(strWalletFile);
304
305     // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
306     TxItems txOrdered;
307
308     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
309     // would make this much faster for applications that do this a lot.
310     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
311     {
312         CWalletTx* wtx = &((*it).second);
313         txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
314     }
315     acentries.clear();
316     walletdb.ListAccountCreditDebit(strAccount, acentries);
317     BOOST_FOREACH(CAccountingEntry& entry, acentries)
318     {
319         txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
320     }
321
322     return txOrdered;
323 }
324
325 void CWallet::WalletUpdateSpent(const CTransaction &tx)
326 {
327     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
328     // Update the wallet spent flag if it doesn't know due to wallet.dat being
329     // restored from backup or the user making copies of wallet.dat.
330     {
331         LOCK(cs_wallet);
332         BOOST_FOREACH(const CTxIn& txin, tx.vin)
333         {
334             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
335             if (mi != mapWallet.end())
336             {
337                 CWalletTx& wtx = (*mi).second;
338                 if (txin.prevout.n >= wtx.vout.size())
339                     printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
340                 else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
341                 {
342                     printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
343                     wtx.MarkSpent(txin.prevout.n);
344                     wtx.WriteToDisk();
345                     NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
346                 }
347             }
348         }
349     }
350 }
351
352 void CWallet::MarkDirty()
353 {
354     {
355         LOCK(cs_wallet);
356         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
357             item.second.MarkDirty();
358     }
359 }
360
361 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
362 {
363     uint256 hash = wtxIn.GetHash();
364     {
365         LOCK(cs_wallet);
366         // Inserts only if not already there, returns tx inserted or tx found
367         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
368         CWalletTx& wtx = (*ret.first).second;
369         wtx.BindWallet(this);
370         bool fInsertedNew = ret.second;
371         if (fInsertedNew)
372         {
373             wtx.nTimeReceived = GetAdjustedTime();
374             wtx.nOrderPos = IncOrderPosNext();
375
376             wtx.nTimeSmart = wtx.nTimeReceived;
377             if (wtxIn.hashBlock != 0)
378             {
379                 if (mapBlockIndex.count(wtxIn.hashBlock))
380                 {
381                     unsigned int latestNow = wtx.nTimeReceived;
382                     unsigned int latestEntry = 0;
383                     {
384                         // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
385                         int64 latestTolerated = latestNow + 300;
386                         std::list<CAccountingEntry> acentries;
387                         TxItems txOrdered = OrderedTxItems(acentries);
388                         for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
389                         {
390                             CWalletTx *const pwtx = (*it).second.first;
391                             if (pwtx == &wtx)
392                                 continue;
393                             CAccountingEntry *const pacentry = (*it).second.second;
394                             int64 nSmartTime;
395                             if (pwtx)
396                             {
397                                 nSmartTime = pwtx->nTimeSmart;
398                                 if (!nSmartTime)
399                                     nSmartTime = pwtx->nTimeReceived;
400                             }
401                             else
402                                 nSmartTime = pacentry->nTime;
403                             if (nSmartTime <= latestTolerated)
404                             {
405                                 latestEntry = nSmartTime;
406                                 if (nSmartTime > latestNow)
407                                     latestNow = nSmartTime;
408                                 break;
409                             }
410                         }
411                     }
412
413                     unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
414                     wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
415                 }
416                 else
417                     printf("AddToWallet() : found %s in block %s not in index\n",
418                            wtxIn.GetHash().ToString().substr(0,10).c_str(),
419                            wtxIn.hashBlock.ToString().c_str());
420             }
421         }
422
423         bool fUpdated = false;
424         if (!fInsertedNew)
425         {
426             // Merge
427             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
428             {
429                 wtx.hashBlock = wtxIn.hashBlock;
430                 fUpdated = true;
431             }
432             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
433             {
434                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
435                 wtx.nIndex = wtxIn.nIndex;
436                 fUpdated = true;
437             }
438             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
439             {
440                 wtx.fFromMe = wtxIn.fFromMe;
441                 fUpdated = true;
442             }
443             fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
444         }
445
446         //// debug print
447         printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
448
449         // Write to disk
450         if (fInsertedNew || fUpdated)
451             if (!wtx.WriteToDisk())
452                 return false;
453 #ifndef QT_GUI
454         // If default receiving address gets used, replace it with a new one
455         CScript scriptDefaultKey;
456         scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
457         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
458         {
459             if (txout.scriptPubKey == scriptDefaultKey)
460             {
461                 CPubKey newDefaultKey;
462                 if (GetKeyFromPool(newDefaultKey, false))
463                 {
464                     SetDefaultKey(newDefaultKey);
465                     SetAddressBookName(vchDefaultKey.GetID(), "");
466                 }
467             }
468         }
469 #endif
470         // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
471         WalletUpdateSpent(wtx);
472
473         // Notify UI of new or updated transaction
474         NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
475     }
476     return true;
477 }
478
479 // Add a transaction to the wallet, or update it.
480 // pblock is optional, but should be provided if the transaction is known to be in a block.
481 // If fUpdate is true, existing transactions will be updated.
482 bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
483 {
484     {
485         LOCK(cs_wallet);
486         bool fExisted = mapWallet.count(hash);
487         if (fExisted && !fUpdate) return false;
488         if (fExisted || IsMine(tx) || IsFromMe(tx))
489         {
490             CWalletTx wtx(this,tx);
491             // Get merkle branch if transaction was found in a block
492             if (pblock)
493                 wtx.SetMerkleBranch(pblock);
494             return AddToWallet(wtx);
495         }
496         else
497             WalletUpdateSpent(tx);
498     }
499     return false;
500 }
501
502 bool CWallet::EraseFromWallet(uint256 hash)
503 {
504     if (!fFileBacked)
505         return false;
506     {
507         LOCK(cs_wallet);
508         if (mapWallet.erase(hash))
509             CWalletDB(strWalletFile).EraseTx(hash);
510     }
511     return true;
512 }
513
514
515 bool CWallet::IsMine(const CTxIn &txin) const
516 {
517     {
518         LOCK(cs_wallet);
519         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
520         if (mi != mapWallet.end())
521         {
522             const CWalletTx& prev = (*mi).second;
523             if (txin.prevout.n < prev.vout.size())
524                 if (IsMine(prev.vout[txin.prevout.n]))
525                     return true;
526         }
527     }
528     return false;
529 }
530
531 int64 CWallet::GetDebit(const CTxIn &txin) const
532 {
533     {
534         LOCK(cs_wallet);
535         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
536         if (mi != mapWallet.end())
537         {
538             const CWalletTx& prev = (*mi).second;
539             if (txin.prevout.n < prev.vout.size())
540                 if (IsMine(prev.vout[txin.prevout.n]))
541                     return prev.vout[txin.prevout.n].nValue;
542         }
543     }
544     return 0;
545 }
546
547 bool CWallet::IsChange(const CTxOut& txout) const
548 {
549     CTxDestination address;
550
551     // TODO: fix handling of 'change' outputs. The assumption is that any
552     // payment to a TX_PUBKEYHASH that is mine but isn't in the address book
553     // is change. That assumption is likely to break when we implement multisignature
554     // wallets that return change back into a multi-signature-protected address;
555     // a better way of identifying which outputs are 'the send' and which are
556     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
557     // which output, if any, was change).
558     if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
559     {
560         LOCK(cs_wallet);
561         if (!mapAddressBook.count(address))
562             return true;
563     }
564     return false;
565 }
566
567 int64 CWalletTx::GetTxTime() const
568 {
569     int64 n = nTimeSmart;
570     return n ? n : nTimeReceived;
571 }
572
573 int CWalletTx::GetRequestCount() const
574 {
575     // Returns -1 if it wasn't being tracked
576     int nRequests = -1;
577     {
578         LOCK(pwallet->cs_wallet);
579         if (IsCoinBase())
580         {
581             // Generated block
582             if (hashBlock != 0)
583             {
584                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
585                 if (mi != pwallet->mapRequestCount.end())
586                     nRequests = (*mi).second;
587             }
588         }
589         else
590         {
591             // Did anyone request this transaction?
592             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
593             if (mi != pwallet->mapRequestCount.end())
594             {
595                 nRequests = (*mi).second;
596
597                 // How about the block it's in?
598                 if (nRequests == 0 && hashBlock != 0)
599                 {
600                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
601                     if (mi != pwallet->mapRequestCount.end())
602                         nRequests = (*mi).second;
603                     else
604                         nRequests = 1; // If it's in someone else's block it must have got out
605                 }
606             }
607         }
608     }
609     return nRequests;
610 }
611
612 void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
613                            list<pair<CTxDestination, int64> >& listSent, int64& nFee, string& strSentAccount) const
614 {
615     nFee = 0;
616     listReceived.clear();
617     listSent.clear();
618     strSentAccount = strFromAccount;
619
620     // Compute fee:
621     int64 nDebit = GetDebit();
622     if (nDebit > 0) // debit>0 means we signed/sent this transaction
623     {
624         int64 nValueOut = GetValueOut();
625         nFee = nDebit - nValueOut;
626     }
627
628     // Sent/received.
629     BOOST_FOREACH(const CTxOut& txout, vout)
630     {
631         CTxDestination address;
632         vector<unsigned char> vchPubKey;
633         if (!ExtractDestination(txout.scriptPubKey, address))
634         {
635             printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
636                    this->GetHash().ToString().c_str());
637         }
638
639         // Don't report 'change' txouts
640         if (nDebit > 0 && pwallet->IsChange(txout))
641             continue;
642
643         if (nDebit > 0)
644             listSent.push_back(make_pair(address, txout.nValue));
645
646         if (pwallet->IsMine(txout))
647             listReceived.push_back(make_pair(address, txout.nValue));
648     }
649
650 }
651
652 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nReceived,
653                                   int64& nSent, int64& nFee) const
654 {
655     nReceived = nSent = nFee = 0;
656
657     int64 allFee;
658     string strSentAccount;
659     list<pair<CTxDestination, int64> > listReceived;
660     list<pair<CTxDestination, int64> > listSent;
661     GetAmounts(listReceived, listSent, allFee, strSentAccount);
662
663     if (strAccount == strSentAccount)
664     {
665         BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& s, listSent)
666             nSent += s.second;
667         nFee = allFee;
668     }
669     {
670         LOCK(pwallet->cs_wallet);
671         BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived)
672         {
673             if (pwallet->mapAddressBook.count(r.first))
674             {
675                 map<CTxDestination, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
676                 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
677                     nReceived += r.second;
678             }
679             else if (strAccount.empty())
680             {
681                 nReceived += r.second;
682             }
683         }
684     }
685 }
686
687 void CWalletTx::AddSupportingTransactions()
688 {
689     vtxPrev.clear();
690
691     const int COPY_DEPTH = 3;
692     if (SetMerkleBranch() < COPY_DEPTH)
693     {
694         vector<uint256> vWorkQueue;
695         BOOST_FOREACH(const CTxIn& txin, vin)
696             vWorkQueue.push_back(txin.prevout.hash);
697
698         {
699             LOCK(pwallet->cs_wallet);
700             map<uint256, const CMerkleTx*> mapWalletPrev;
701             set<uint256> setAlreadyDone;
702             for (unsigned int i = 0; i < vWorkQueue.size(); i++)
703             {
704                 uint256 hash = vWorkQueue[i];
705                 if (setAlreadyDone.count(hash))
706                     continue;
707                 setAlreadyDone.insert(hash);
708
709                 CMerkleTx tx;
710                 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
711                 if (mi != pwallet->mapWallet.end())
712                 {
713                     tx = (*mi).second;
714                     BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
715                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
716                 }
717                 else if (mapWalletPrev.count(hash))
718                 {
719                     tx = *mapWalletPrev[hash];
720                 }
721
722                 int nDepth = tx.SetMerkleBranch();
723                 vtxPrev.push_back(tx);
724
725                 if (nDepth < COPY_DEPTH)
726                 {
727                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
728                         vWorkQueue.push_back(txin.prevout.hash);
729                 }
730             }
731         }
732     }
733
734     reverse(vtxPrev.begin(), vtxPrev.end());
735 }
736
737 bool CWalletTx::WriteToDisk()
738 {
739     return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
740 }
741
742 // Scan the block chain (starting in pindexStart) for transactions
743 // from or to us. If fUpdate is true, found transactions that already
744 // exist in the wallet will be updated.
745 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
746 {
747     int ret = 0;
748
749     CBlockIndex* pindex = pindexStart;
750     {
751         LOCK(cs_wallet);
752         while (pindex)
753         {
754             CBlock block;
755             block.ReadFromDisk(pindex, true);
756             BOOST_FOREACH(CTransaction& tx, block.vtx)
757             {
758                 if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
759                     ret++;
760             }
761             pindex = pindex->pnext;
762         }
763     }
764     return ret;
765 }
766
767 void CWallet::ReacceptWalletTransactions()
768 {
769     bool fRepeat = true;
770     while (fRepeat)
771     {
772         LOCK(cs_wallet);
773         fRepeat = false;
774         bool fMissing = false;
775         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
776         {
777             CWalletTx& wtx = item.second;
778             if (wtx.IsCoinBase() && wtx.IsSpent(0))
779                 continue;
780
781             CCoins coins;
782             bool fUpdated = false;
783             bool fNotFound = pcoinsTip->GetCoins(wtx.GetHash(), coins);
784             if (!fNotFound || wtx.GetDepthInMainChain() > 0)
785             {
786                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
787                 for (unsigned int i = 0; i < wtx.vout.size(); i++)
788                 {
789                     if (wtx.IsSpent(i))
790                         continue;
791                     if ((i >= coins.vout.size() || coins.vout[i].IsNull()) && IsMine(wtx.vout[i]))
792                     {
793                         wtx.MarkSpent(i);
794                         fUpdated = true;
795                         fMissing = true;
796                     }
797                 }
798                 if (fUpdated)
799                 {
800                     printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
801                     wtx.MarkDirty();
802                     wtx.WriteToDisk();
803                 }
804             }
805             else
806             {
807                 // Re-accept any txes of ours that aren't already in a block
808                 if (!wtx.IsCoinBase())
809                     wtx.AcceptWalletTransaction(false);
810             }
811         }
812         if (fMissing)
813         {
814             // TODO: optimize this to scan just part of the block chain?
815             if (ScanForWalletTransactions(pindexGenesisBlock))
816                 fRepeat = true;  // Found missing transactions: re-do re-accept.
817         }
818     }
819 }
820
821 void CWalletTx::RelayWalletTransaction()
822 {
823     CCoinsViewCache& coins = *pcoinsTip;
824     BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
825     {
826         if (!tx.IsCoinBase())
827         {
828             uint256 hash = tx.GetHash();
829             if (!coins.HaveCoins(hash))
830                 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
831         }
832     }
833     if (!IsCoinBase())
834     {
835         uint256 hash = GetHash();
836         if (!coins.HaveCoins(hash))
837         {
838             printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
839             RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
840         }
841     }
842 }
843
844 void CWallet::ResendWalletTransactions()
845 {
846     // Do this infrequently and randomly to avoid giving away
847     // that these are our transactions.
848     static int64 nNextTime;
849     if (GetTime() < nNextTime)
850         return;
851     bool fFirst = (nNextTime == 0);
852     nNextTime = GetTime() + GetRand(30 * 60);
853     if (fFirst)
854         return;
855
856     // Only do it if there's been a new block since last time
857     static int64 nLastTime;
858     if (nTimeBestReceived < nLastTime)
859         return;
860     nLastTime = GetTime();
861
862     // Rebroadcast any of our txes that aren't in a block yet
863     printf("ResendWalletTransactions()\n");
864     {
865         LOCK(cs_wallet);
866         // Sort them in chronological order
867         multimap<unsigned int, CWalletTx*> mapSorted;
868         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
869         {
870             CWalletTx& wtx = item.second;
871             // Don't rebroadcast until it's had plenty of time that
872             // it should have gotten in already by now.
873             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
874                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
875         }
876         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
877         {
878             CWalletTx& wtx = *item.second;
879             wtx.RelayWalletTransaction();
880         }
881     }
882 }
883
884
885
886
887
888
889 //////////////////////////////////////////////////////////////////////////////
890 //
891 // Actions
892 //
893
894
895 int64 CWallet::GetBalance() const
896 {
897     int64 nTotal = 0;
898     {
899         LOCK(cs_wallet);
900         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
901         {
902             const CWalletTx* pcoin = &(*it).second;
903             if (pcoin->IsFinal() && pcoin->IsConfirmed())
904                 nTotal += pcoin->GetAvailableCredit();
905         }
906     }
907
908     return nTotal;
909 }
910
911 int64 CWallet::GetUnconfirmedBalance() const
912 {
913     int64 nTotal = 0;
914     {
915         LOCK(cs_wallet);
916         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
917         {
918             const CWalletTx* pcoin = &(*it).second;
919             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
920                 nTotal += pcoin->GetAvailableCredit();
921         }
922     }
923     return nTotal;
924 }
925
926 int64 CWallet::GetImmatureBalance() const
927 {
928     int64 nTotal = 0;
929     {
930         LOCK(cs_wallet);
931         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
932         {
933             const CWalletTx& pcoin = (*it).second;
934             if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain())
935                 nTotal += GetCredit(pcoin);
936         }
937     }
938     return nTotal;
939 }
940
941 // populate vCoins with vector of spendable COutputs
942 void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
943 {
944     vCoins.clear();
945
946     {
947         LOCK(cs_wallet);
948         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
949         {
950             const CWalletTx* pcoin = &(*it).second;
951
952             if (!pcoin->IsFinal())
953                 continue;
954
955             if (fOnlyConfirmed && !pcoin->IsConfirmed())
956                 continue;
957
958             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
959                 continue;
960
961             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
962                 if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue > 0)
963                     vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
964         }
965     }
966 }
967
968 static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsigned int> > >vValue, int64 nTotalLower, int64 nTargetValue,
969                                   vector<char>& vfBest, int64& nBest, int iterations = 1000)
970 {
971     vector<char> vfIncluded;
972
973     vfBest.assign(vValue.size(), true);
974     nBest = nTotalLower;
975
976     for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
977     {
978         vfIncluded.assign(vValue.size(), false);
979         int64 nTotal = 0;
980         bool fReachedTarget = false;
981         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
982         {
983             for (unsigned int i = 0; i < vValue.size(); i++)
984             {
985                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
986                 {
987                     nTotal += vValue[i].first;
988                     vfIncluded[i] = true;
989                     if (nTotal >= nTargetValue)
990                     {
991                         fReachedTarget = true;
992                         if (nTotal < nBest)
993                         {
994                             nBest = nTotal;
995                             vfBest = vfIncluded;
996                         }
997                         nTotal -= vValue[i].first;
998                         vfIncluded[i] = false;
999                     }
1000                 }
1001             }
1002         }
1003     }
1004 }
1005
1006 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
1007                                  set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1008 {
1009     setCoinsRet.clear();
1010     nValueRet = 0;
1011
1012     // List of values less than target
1013     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
1014     coinLowestLarger.first = std::numeric_limits<int64>::max();
1015     coinLowestLarger.second.first = NULL;
1016     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
1017     int64 nTotalLower = 0;
1018
1019     random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
1020
1021     BOOST_FOREACH(COutput output, vCoins)
1022     {
1023         const CWalletTx *pcoin = output.tx;
1024
1025         if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
1026             continue;
1027
1028         int i = output.i;
1029         int64 n = pcoin->vout[i].nValue;
1030
1031         pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1032
1033         if (n == nTargetValue)
1034         {
1035             setCoinsRet.insert(coin.second);
1036             nValueRet += coin.first;
1037             return true;
1038         }
1039         else if (n < nTargetValue + CENT)
1040         {
1041             vValue.push_back(coin);
1042             nTotalLower += n;
1043         }
1044         else if (n < coinLowestLarger.first)
1045         {
1046             coinLowestLarger = coin;
1047         }
1048     }
1049
1050     if (nTotalLower == nTargetValue)
1051     {
1052         for (unsigned int i = 0; i < vValue.size(); ++i)
1053         {
1054             setCoinsRet.insert(vValue[i].second);
1055             nValueRet += vValue[i].first;
1056         }
1057         return true;
1058     }
1059
1060     if (nTotalLower < nTargetValue)
1061     {
1062         if (coinLowestLarger.second.first == NULL)
1063             return false;
1064         setCoinsRet.insert(coinLowestLarger.second);
1065         nValueRet += coinLowestLarger.first;
1066         return true;
1067     }
1068
1069     // Solve subset sum by stochastic approximation
1070     sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1071     vector<char> vfBest;
1072     int64 nBest;
1073
1074     ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
1075     if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
1076         ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1077
1078     // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
1079     //                                   or the next bigger coin is closer), return the bigger coin
1080     if (coinLowestLarger.second.first &&
1081         ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
1082     {
1083         setCoinsRet.insert(coinLowestLarger.second);
1084         nValueRet += coinLowestLarger.first;
1085     }
1086     else {
1087         for (unsigned int i = 0; i < vValue.size(); i++)
1088             if (vfBest[i])
1089             {
1090                 setCoinsRet.insert(vValue[i].second);
1091                 nValueRet += vValue[i].first;
1092             }
1093
1094         //// debug print
1095         printf("SelectCoins() best subset: ");
1096         for (unsigned int i = 0; i < vValue.size(); i++)
1097             if (vfBest[i])
1098                 printf("%s ", FormatMoney(vValue[i].first).c_str());
1099         printf("total %s\n", FormatMoney(nBest).c_str());
1100     }
1101
1102     return true;
1103 }
1104
1105 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1106 {
1107     vector<COutput> vCoins;
1108     AvailableCoins(vCoins);
1109
1110     return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
1111             SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
1112             SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet));
1113 }
1114
1115
1116
1117
1118 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1119 {
1120     int64 nValue = 0;
1121     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1122     {
1123         if (nValue < 0)
1124             return false;
1125         nValue += s.second;
1126     }
1127     if (vecSend.empty() || nValue < 0)
1128         return false;
1129
1130     wtxNew.BindWallet(this);
1131
1132     {
1133         LOCK2(cs_main, cs_wallet);
1134         {
1135             nFeeRet = nTransactionFee;
1136             loop
1137             {
1138                 wtxNew.vin.clear();
1139                 wtxNew.vout.clear();
1140                 wtxNew.fFromMe = true;
1141
1142                 int64 nTotalValue = nValue + nFeeRet;
1143                 double dPriority = 0;
1144                 // vouts to the payees
1145                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1146                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
1147
1148                 // Choose coins to use
1149                 set<pair<const CWalletTx*,unsigned int> > setCoins;
1150                 int64 nValueIn = 0;
1151                 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
1152                     return false;
1153                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1154                 {
1155                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
1156                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
1157                 }
1158
1159                 int64 nChange = nValueIn - nValue - nFeeRet;
1160                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
1161                 // or until nChange becomes zero
1162                 // NOTE: this depends on the exact behaviour of GetMinFee
1163                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
1164                 {
1165                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
1166                     nChange -= nMoveToFee;
1167                     nFeeRet += nMoveToFee;
1168                 }
1169
1170                 if (nChange > 0)
1171                 {
1172                     // Note: We use a new key here to keep it from being obvious which side is the change.
1173                     //  The drawback is that by not reusing a previous key, the change may be lost if a
1174                     //  backup is restored, if the backup doesn't have the new private key for the change.
1175                     //  If we reused the old key, it would be possible to add code to look for and
1176                     //  rediscover unknown transactions that were written with keys of ours to recover
1177                     //  post-backup change.
1178
1179                     // Reserve a new key pair from key pool
1180                     CPubKey vchPubKey = reservekey.GetReservedKey();
1181                     // assert(mapKeys.count(vchPubKey));
1182
1183                     // Fill a vout to ourself
1184                     // TODO: pass in scriptChange instead of reservekey so
1185                     // change transaction isn't always pay-to-bitcoin-address
1186                     CScript scriptChange;
1187                     scriptChange.SetDestination(vchPubKey.GetID());
1188
1189                     // Insert change txn at random position:
1190                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
1191                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
1192                 }
1193                 else
1194                     reservekey.ReturnKey();
1195
1196                 // Fill vin
1197                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1198                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1199
1200                 // Sign
1201                 int nIn = 0;
1202                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1203                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1204                         return false;
1205
1206                 // Limit size
1207                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1208                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1209                     return false;
1210                 dPriority /= nBytes;
1211
1212                 // Check that enough fee is included
1213                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1214                 bool fAllowFree = CTransaction::AllowFree(dPriority);
1215                 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND);
1216                 if (nFeeRet < max(nPayFee, nMinFee))
1217                 {
1218                     nFeeRet = max(nPayFee, nMinFee);
1219                     continue;
1220                 }
1221
1222                 // Fill vtxPrev by copying from previous transactions vtxPrev
1223                 wtxNew.AddSupportingTransactions();
1224                 wtxNew.fTimeReceivedIsTxTime = true;
1225
1226                 break;
1227             }
1228         }
1229     }
1230     return true;
1231 }
1232
1233 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1234 {
1235     vector< pair<CScript, int64> > vecSend;
1236     vecSend.push_back(make_pair(scriptPubKey, nValue));
1237     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
1238 }
1239
1240 // Call after CreateTransaction unless you want to abort
1241 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1242 {
1243     {
1244         LOCK2(cs_main, cs_wallet);
1245         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1246         {
1247             // This is only to keep the database open to defeat the auto-flush for the
1248             // duration of this scope.  This is the only place where this optimization
1249             // maybe makes sense; please don't do it anywhere else.
1250             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1251
1252             // Take key pair from key pool so it won't be used again
1253             reservekey.KeepKey();
1254
1255             // Add tx to wallet, because if it has change it's also ours,
1256             // otherwise just for transaction history.
1257             AddToWallet(wtxNew);
1258
1259             // Mark old coins as spent
1260             set<CWalletTx*> setCoins;
1261             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1262             {
1263                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1264                 coin.BindWallet(this);
1265                 coin.MarkSpent(txin.prevout.n);
1266                 coin.WriteToDisk();
1267                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1268             }
1269
1270             if (fFileBacked)
1271                 delete pwalletdb;
1272         }
1273
1274         // Track how many getdata requests our transaction gets
1275         mapRequestCount[wtxNew.GetHash()] = 0;
1276
1277         // Broadcast
1278         if (!wtxNew.AcceptToMemoryPool())
1279         {
1280             // This must not fail. The transaction has already been signed and recorded.
1281             printf("CommitTransaction() : Error: Transaction not valid");
1282             return false;
1283         }
1284         wtxNew.RelayWalletTransaction();
1285     }
1286     return true;
1287 }
1288
1289
1290
1291
1292 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1293 {
1294     CReserveKey reservekey(this);
1295     int64 nFeeRequired;
1296
1297     if (IsLocked())
1298     {
1299         string strError = _("Error: Wallet locked, unable to create transaction  ");
1300         printf("SendMoney() : %s", strError.c_str());
1301         return strError;
1302     }
1303     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1304     {
1305         string strError;
1306         if (nValue + nFeeRequired > GetBalance())
1307             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).c_str());
1308         else
1309             strError = _("Error: Transaction creation failed  ");
1310         printf("SendMoney() : %s", strError.c_str());
1311         return strError;
1312     }
1313
1314     if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending...")))
1315         return "ABORTED";
1316
1317     if (!CommitTransaction(wtxNew, reservekey))
1318         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.");
1319
1320     return "";
1321 }
1322
1323
1324
1325 string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1326 {
1327     // Check amount
1328     if (nValue <= 0)
1329         return _("Invalid amount");
1330     if (nValue + nTransactionFee > GetBalance())
1331         return _("Insufficient funds");
1332
1333     // Parse Bitcoin address
1334     CScript scriptPubKey;
1335     scriptPubKey.SetDestination(address);
1336
1337     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1338 }
1339
1340
1341
1342
1343 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1344 {
1345     if (!fFileBacked)
1346         return DB_LOAD_OK;
1347     fFirstRunRet = false;
1348     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1349     if (nLoadWalletRet == DB_NEED_REWRITE)
1350     {
1351         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1352         {
1353             setKeyPool.clear();
1354             // Note: can't top-up keypool here, because wallet is locked.
1355             // User will be prompted to unlock wallet the next operation
1356             // the requires a new key.
1357         }
1358     }
1359
1360     if (nLoadWalletRet != DB_LOAD_OK)
1361         return nLoadWalletRet;
1362     fFirstRunRet = !vchDefaultKey.IsValid();
1363
1364     NewThread(ThreadFlushWalletDB, &strWalletFile);
1365     return DB_LOAD_OK;
1366 }
1367
1368
1369 bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
1370 {
1371     std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
1372     mapAddressBook[address] = strName;
1373     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
1374     if (!fFileBacked)
1375         return false;
1376     return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1377 }
1378
1379 bool CWallet::DelAddressBookName(const CTxDestination& address)
1380 {
1381     mapAddressBook.erase(address);
1382     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
1383     if (!fFileBacked)
1384         return false;
1385     return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1386 }
1387
1388
1389 void CWallet::PrintWallet(const CBlock& block)
1390 {
1391     {
1392         LOCK(cs_wallet);
1393         if (mapWallet.count(block.vtx[0].GetHash()))
1394         {
1395             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1396             printf("    mine:  %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1397         }
1398     }
1399     printf("\n");
1400 }
1401
1402 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1403 {
1404     {
1405         LOCK(cs_wallet);
1406         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1407         if (mi != mapWallet.end())
1408         {
1409             wtx = (*mi).second;
1410             return true;
1411         }
1412     }
1413     return false;
1414 }
1415
1416 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1417 {
1418     if (fFileBacked)
1419     {
1420         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1421             return false;
1422     }
1423     vchDefaultKey = vchPubKey;
1424     return true;
1425 }
1426
1427 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1428 {
1429     if (!pwallet->fFileBacked)
1430         return false;
1431     strWalletFileOut = pwallet->strWalletFile;
1432     return true;
1433 }
1434
1435 //
1436 // Mark old keypool keys as used,
1437 // and generate all new keys
1438 //
1439 bool CWallet::NewKeyPool()
1440 {
1441     {
1442         LOCK(cs_wallet);
1443         CWalletDB walletdb(strWalletFile);
1444         BOOST_FOREACH(int64 nIndex, setKeyPool)
1445             walletdb.ErasePool(nIndex);
1446         setKeyPool.clear();
1447
1448         if (IsLocked())
1449             return false;
1450
1451         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1452         for (int i = 0; i < nKeys; i++)
1453         {
1454             int64 nIndex = i+1;
1455             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1456             setKeyPool.insert(nIndex);
1457         }
1458         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1459     }
1460     return true;
1461 }
1462
1463 bool CWallet::TopUpKeyPool()
1464 {
1465     {
1466         LOCK(cs_wallet);
1467
1468         if (IsLocked())
1469             return false;
1470
1471         CWalletDB walletdb(strWalletFile);
1472
1473         // Top up key pool
1474         unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
1475         while (setKeyPool.size() < (nTargetSize + 1))
1476         {
1477             int64 nEnd = 1;
1478             if (!setKeyPool.empty())
1479                 nEnd = *(--setKeyPool.end()) + 1;
1480             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1481                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1482             setKeyPool.insert(nEnd);
1483             printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1484         }
1485     }
1486     return true;
1487 }
1488
1489 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1490 {
1491     nIndex = -1;
1492     keypool.vchPubKey = CPubKey();
1493     {
1494         LOCK(cs_wallet);
1495
1496         if (!IsLocked())
1497             TopUpKeyPool();
1498
1499         // Get the oldest key
1500         if(setKeyPool.empty())
1501             return;
1502
1503         CWalletDB walletdb(strWalletFile);
1504
1505         nIndex = *(setKeyPool.begin());
1506         setKeyPool.erase(setKeyPool.begin());
1507         if (!walletdb.ReadPool(nIndex, keypool))
1508             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1509         if (!HaveKey(keypool.vchPubKey.GetID()))
1510             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1511         assert(keypool.vchPubKey.IsValid());
1512         printf("keypool reserve %"PRI64d"\n", nIndex);
1513     }
1514 }
1515
1516 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
1517 {
1518     {
1519         LOCK2(cs_main, cs_wallet);
1520         CWalletDB walletdb(strWalletFile);
1521
1522         int64 nIndex = 1 + *(--setKeyPool.end());
1523         if (!walletdb.WritePool(nIndex, keypool))
1524             throw runtime_error("AddReserveKey() : writing added key failed");
1525         setKeyPool.insert(nIndex);
1526         return nIndex;
1527     }
1528     return -1;
1529 }
1530
1531 void CWallet::KeepKey(int64 nIndex)
1532 {
1533     // Remove from key pool
1534     if (fFileBacked)
1535     {
1536         CWalletDB walletdb(strWalletFile);
1537         walletdb.ErasePool(nIndex);
1538     }
1539     printf("keypool keep %"PRI64d"\n", nIndex);
1540 }
1541
1542 void CWallet::ReturnKey(int64 nIndex)
1543 {
1544     // Return to key pool
1545     {
1546         LOCK(cs_wallet);
1547         setKeyPool.insert(nIndex);
1548     }
1549     printf("keypool return %"PRI64d"\n", nIndex);
1550 }
1551
1552 bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
1553 {
1554     int64 nIndex = 0;
1555     CKeyPool keypool;
1556     {
1557         LOCK(cs_wallet);
1558         ReserveKeyFromKeyPool(nIndex, keypool);
1559         if (nIndex == -1)
1560         {
1561             if (fAllowReuse && vchDefaultKey.IsValid())
1562             {
1563                 result = vchDefaultKey;
1564                 return true;
1565             }
1566             if (IsLocked()) return false;
1567             result = GenerateNewKey();
1568             return true;
1569         }
1570         KeepKey(nIndex);
1571         result = keypool.vchPubKey;
1572     }
1573     return true;
1574 }
1575
1576 int64 CWallet::GetOldestKeyPoolTime()
1577 {
1578     int64 nIndex = 0;
1579     CKeyPool keypool;
1580     ReserveKeyFromKeyPool(nIndex, keypool);
1581     if (nIndex == -1)
1582         return GetTime();
1583     ReturnKey(nIndex);
1584     return keypool.nTime;
1585 }
1586
1587 std::map<CTxDestination, int64> CWallet::GetAddressBalances()
1588 {
1589     map<CTxDestination, int64> balances;
1590
1591     {
1592         LOCK(cs_wallet);
1593         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1594         {
1595             CWalletTx *pcoin = &walletEntry.second;
1596
1597             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
1598                 continue;
1599
1600             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1601                 continue;
1602
1603             int nDepth = pcoin->GetDepthInMainChain();
1604             if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
1605                 continue;
1606
1607             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1608             {
1609                 CTxDestination addr;
1610                 if (!IsMine(pcoin->vout[i]))
1611                     continue;
1612                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
1613                     continue;
1614
1615                 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
1616
1617                 if (!balances.count(addr))
1618                     balances[addr] = 0;
1619                 balances[addr] += n;
1620             }
1621         }
1622     }
1623
1624     return balances;
1625 }
1626
1627 set< set<CTxDestination> > CWallet::GetAddressGroupings()
1628 {
1629     set< set<CTxDestination> > groupings;
1630     set<CTxDestination> grouping;
1631
1632     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
1633     {
1634         CWalletTx *pcoin = &walletEntry.second;
1635
1636         if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0]))
1637         {
1638             // group all input addresses with each other
1639             BOOST_FOREACH(CTxIn txin, pcoin->vin)
1640             {
1641                 CTxDestination address;
1642                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
1643                     continue;
1644                 grouping.insert(address);
1645             }
1646
1647             // group change with input addresses
1648             BOOST_FOREACH(CTxOut txout, pcoin->vout)
1649                 if (IsChange(txout))
1650                 {
1651                     CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash];
1652                     CTxDestination txoutAddr;
1653                     if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
1654                         continue;
1655                     grouping.insert(txoutAddr);
1656                 }
1657             groupings.insert(grouping);
1658             grouping.clear();
1659         }
1660
1661         // group lone addrs by themselves
1662         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1663             if (IsMine(pcoin->vout[i]))
1664             {
1665                 CTxDestination address;
1666                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
1667                     continue;
1668                 grouping.insert(address);
1669                 groupings.insert(grouping);
1670                 grouping.clear();
1671             }
1672     }
1673
1674     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
1675     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
1676     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
1677     {
1678         // make a set of all the groups hit by this new group
1679         set< set<CTxDestination>* > hits;
1680         map< CTxDestination, set<CTxDestination>* >::iterator it;
1681         BOOST_FOREACH(CTxDestination address, grouping)
1682             if ((it = setmap.find(address)) != setmap.end())
1683                 hits.insert((*it).second);
1684
1685         // merge all hit groups into a new single group and delete old groups
1686         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
1687         BOOST_FOREACH(set<CTxDestination>* hit, hits)
1688         {
1689             merged->insert(hit->begin(), hit->end());
1690             uniqueGroupings.erase(hit);
1691             delete hit;
1692         }
1693         uniqueGroupings.insert(merged);
1694
1695         // update setmap
1696         BOOST_FOREACH(CTxDestination element, *merged)
1697             setmap[element] = merged;
1698     }
1699
1700     set< set<CTxDestination> > ret;
1701     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
1702     {
1703         ret.insert(*uniqueGrouping);
1704         delete uniqueGrouping;
1705     }
1706
1707     return ret;
1708 }
1709
1710 CPubKey CReserveKey::GetReservedKey()
1711 {
1712     if (nIndex == -1)
1713     {
1714         CKeyPool keypool;
1715         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1716         if (nIndex != -1)
1717             vchPubKey = keypool.vchPubKey;
1718         else
1719         {
1720             printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
1721             vchPubKey = pwallet->vchDefaultKey;
1722         }
1723     }
1724     assert(vchPubKey.IsValid());
1725     return vchPubKey;
1726 }
1727
1728 void CReserveKey::KeepKey()
1729 {
1730     if (nIndex != -1)
1731         pwallet->KeepKey(nIndex);
1732     nIndex = -1;
1733     vchPubKey = CPubKey();
1734 }
1735
1736 void CReserveKey::ReturnKey()
1737 {
1738     if (nIndex != -1)
1739         pwallet->ReturnKey(nIndex);
1740     nIndex = -1;
1741     vchPubKey = CPubKey();
1742 }
1743
1744 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress)
1745 {
1746     setAddress.clear();
1747
1748     CWalletDB walletdb(strWalletFile);
1749
1750     LOCK2(cs_main, cs_wallet);
1751     BOOST_FOREACH(const int64& id, setKeyPool)
1752     {
1753         CKeyPool keypool;
1754         if (!walletdb.ReadPool(id, keypool))
1755             throw runtime_error("GetAllReserveKeyHashes() : read failed");
1756         assert(keypool.vchPubKey.IsValid());
1757         CKeyID keyID = keypool.vchPubKey.GetID();
1758         if (!HaveKey(keyID))
1759             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1760         setAddress.insert(keyID);
1761     }
1762 }
1763
1764 void CWallet::UpdatedTransaction(const uint256 &hashTx)
1765 {
1766     {
1767         LOCK(cs_wallet);
1768         // Only notify UI if this transaction is in this wallet
1769         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
1770         if (mi != mapWallet.end())
1771             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
1772     }
1773 }
This page took 0.129142 seconds and 4 git commands to generate.