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