-
+ DA1E35BCCE58F94AE0C44B6C2D8AC21D3B8263A594B93EFA335A6C804A1B115C16A977AB237D78C4E9EB6899FF5C9A108F36A9A2FC9FAD96DDAA2E30267587F7bitcoin/src/wallet.cpp(0 . 0)(1 . 1415)
24623 // Copyright (c) 2009-2010 Satoshi Nakamoto
24624 // Copyright (c) 2011 The Bitcoin developers
24625 // Distributed under the MIT/X11 software license, see the accompanying
24626 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
24627 
24628 #include "headers.h"
24629 #include "db.h"
24630 #include "crypter.h"
24631 
24632 using namespace std;
24633 
24634 
24635 //////////////////////////////////////////////////////////////////////////////
24636 //
24637 // mapWallet
24638 //
24639 
24640 bool CWallet::AddKey(const CKey& key)
24641 {
24642     if (!CCryptoKeyStore::AddKey(key))
24643         return false;
24644     if (!fFileBacked)
24645         return true;
24646     if (!IsCrypted())
24647         return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
24648     return true;
24649 }
24650 
24651 bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
24652 {
24653     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
24654         return false;
24655     if (!fFileBacked)
24656         return true;
24657     CRITICAL_BLOCK(cs_wallet)
24658     {
24659         if (pwalletdbEncryption)
24660             return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
24661         else
24662             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
24663     }
24664     return false;
24665 }
24666 
24667 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
24668 {
24669     if (!IsLocked())
24670         return false;
24671 
24672     CCrypter crypter;
24673     CKeyingMaterial vMasterKey;
24674 
24675     CRITICAL_BLOCK(cs_wallet)
24676         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
24677         {
24678             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
24679                 return false;
24680             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
24681                 return false;
24682             if (CCryptoKeyStore::Unlock(vMasterKey))
24683                 return true;
24684         }
24685     return false;
24686 }
24687 
24688 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
24689 {
24690     bool fWasLocked = IsLocked();
24691 
24692     CRITICAL_BLOCK(cs_wallet)
24693     {
24694         Lock();
24695 
24696         CCrypter crypter;
24697         CKeyingMaterial vMasterKey;
24698         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
24699         {
24700             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
24701                 return false;
24702             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
24703                 return false;
24704             if (CCryptoKeyStore::Unlock(vMasterKey))
24705             {
24706                 int64 nStartTime = GetTimeMillis();
24707                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
24708                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
24709 
24710                 nStartTime = GetTimeMillis();
24711                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
24712                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
24713 
24714                 if (pMasterKey.second.nDeriveIterations < 25000)
24715                     pMasterKey.second.nDeriveIterations = 25000;
24716 
24717                 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
24718 
24719                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
24720                     return false;
24721                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
24722                     return false;
24723                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
24724                 if (fWasLocked)
24725                     Lock();
24726                 return true;
24727             }
24728         }
24729     }
24730 
24731     return false;
24732 }
24733 
24734 
24735 // This class implements an addrIncoming entry that causes pre-0.4
24736 // clients to crash on startup if reading a private-key-encrypted wallet.
24737 class CCorruptAddress
24738 {
24739 public:
24740     IMPLEMENT_SERIALIZE
24741     (
24742         if (nType & SER_DISK)
24743             READWRITE(nVersion);
24744     )
24745 };
24746 
24747 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
24748 {
24749     if (IsCrypted())
24750         return false;
24751 
24752     CKeyingMaterial vMasterKey;
24753     RandAddSeedPerfmon();
24754 
24755     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
24756     RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
24757 
24758     CMasterKey kMasterKey;
24759 
24760     RandAddSeedPerfmon();
24761     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
24762     RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
24763 
24764     CCrypter crypter;
24765     int64 nStartTime = GetTimeMillis();
24766     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
24767     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
24768 
24769     nStartTime = GetTimeMillis();
24770     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
24771     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
24772 
24773     if (kMasterKey.nDeriveIterations < 25000)
24774         kMasterKey.nDeriveIterations = 25000;
24775 
24776     printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
24777 
24778     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
24779         return false;
24780     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
24781         return false;
24782 
24783     CRITICAL_BLOCK(cs_wallet)
24784     {
24785         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
24786         if (fFileBacked)
24787         {
24788             pwalletdbEncryption = new CWalletDB(strWalletFile);
24789             pwalletdbEncryption->TxnBegin();
24790             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
24791         }
24792 
24793         if (!EncryptKeys(vMasterKey))
24794         {
24795             if (fFileBacked)
24796                 pwalletdbEncryption->TxnAbort();
24797             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.
24798         }
24799 
24800         if (fFileBacked)
24801         {
24802             CCorruptAddress corruptAddress;
24803             pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
24804             if (!pwalletdbEncryption->TxnCommit())
24805                 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.
24806 
24807             delete pwalletdbEncryption;
24808             pwalletdbEncryption = NULL;
24809         }
24810 
24811         Lock();
24812         Unlock(strWalletPassphrase);
24813         NewKeyPool();
24814         Lock();
24815 
24816         // Need to completely rewrite the wallet file; if we don't, bdb might keep
24817         // bits of the unencrypted private key in slack space in the database file.
24818         CDB::Rewrite(strWalletFile);
24819     }
24820 
24821     return true;
24822 }
24823 
24824 void CWallet::WalletUpdateSpent(const CTransaction &tx)
24825 {
24826     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
24827     // Update the wallet spent flag if it doesn't know due to wallet.dat being
24828     // restored from backup or the user making copies of wallet.dat.
24829     CRITICAL_BLOCK(cs_wallet)
24830     {
24831         BOOST_FOREACH(const CTxIn& txin, tx.vin)
24832         {
24833             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
24834             if (mi != mapWallet.end())
24835             {
24836                 CWalletTx& wtx = (*mi).second;
24837                 if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
24838                 {
24839                     printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
24840                     wtx.MarkSpent(txin.prevout.n);
24841                     wtx.WriteToDisk();
24842                     vWalletUpdated.push_back(txin.prevout.hash);
24843                 }
24844             }
24845         }
24846     }
24847 }
24848 
24849 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
24850 {
24851     uint256 hash = wtxIn.GetHash();
24852     CRITICAL_BLOCK(cs_wallet)
24853     {
24854         // Inserts only if not already there, returns tx inserted or tx found
24855         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
24856         CWalletTx& wtx = (*ret.first).second;
24857         wtx.pwallet = this;
24858         bool fInsertedNew = ret.second;
24859         if (fInsertedNew)
24860             wtx.nTimeReceived = GetAdjustedTime();
24861 
24862         bool fUpdated = false;
24863         if (!fInsertedNew)
24864         {
24865             // Merge
24866             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
24867             {
24868                 wtx.hashBlock = wtxIn.hashBlock;
24869                 fUpdated = true;
24870             }
24871             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
24872             {
24873                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
24874                 wtx.nIndex = wtxIn.nIndex;
24875                 fUpdated = true;
24876             }
24877             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
24878             {
24879                 wtx.fFromMe = wtxIn.fFromMe;
24880                 fUpdated = true;
24881             }
24882             fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
24883         }
24884 
24885         //// debug print
24886         printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
24887 
24888         // Write to disk
24889         if (fInsertedNew || fUpdated)
24890             if (!wtx.WriteToDisk())
24891                 return false;
24892 #ifndef QT_GUI
24893         // If default receiving address gets used, replace it with a new one
24894         CScript scriptDefaultKey;
24895         scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
24896         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
24897         {
24898             if (txout.scriptPubKey == scriptDefaultKey)
24899             {
24900                 std::vector<unsigned char> newDefaultKey;
24901                 if (GetKeyFromPool(newDefaultKey, false))
24902                 {
24903                     SetDefaultKey(newDefaultKey);
24904                     SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
24905                 }
24906             }
24907         }
24908 #endif
24909         // Notify UI
24910         vWalletUpdated.push_back(hash);
24911 
24912         // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
24913         WalletUpdateSpent(wtx);
24914     }
24915 
24916     // Refresh UI
24917     MainFrameRepaint();
24918     return true;
24919 }
24920 
24921 // Add a transaction to the wallet, or update it.
24922 // pblock is optional, but should be provided if the transaction is known to be in a block.
24923 // If fUpdate is true, existing transactions will be updated.
24924 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
24925 {
24926     uint256 hash = tx.GetHash();
24927     CRITICAL_BLOCK(cs_wallet)
24928     {
24929         bool fExisted = mapWallet.count(hash);
24930         if (fExisted && !fUpdate) return false;
24931         if (fExisted || IsMine(tx) || IsFromMe(tx))
24932         {
24933             CWalletTx wtx(this,tx);
24934             // Get merkle branch if transaction was found in a block
24935             if (pblock)
24936                 wtx.SetMerkleBranch(pblock);
24937             return AddToWallet(wtx);
24938         }
24939         else
24940             WalletUpdateSpent(tx);
24941     }
24942     return false;
24943 }
24944 
24945 bool CWallet::EraseFromWallet(uint256 hash)
24946 {
24947     if (!fFileBacked)
24948         return false;
24949     CRITICAL_BLOCK(cs_wallet)
24950     {
24951         if (mapWallet.erase(hash))
24952             CWalletDB(strWalletFile).EraseTx(hash);
24953     }
24954     return true;
24955 }
24956 
24957 
24958 bool CWallet::IsMine(const CTxIn &txin) const
24959 {
24960     CRITICAL_BLOCK(cs_wallet)
24961     {
24962         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
24963         if (mi != mapWallet.end())
24964         {
24965             const CWalletTx& prev = (*mi).second;
24966             if (txin.prevout.n < prev.vout.size())
24967                 if (IsMine(prev.vout[txin.prevout.n]))
24968                     return true;
24969         }
24970     }
24971     return false;
24972 }
24973 
24974 int64 CWallet::GetDebit(const CTxIn &txin) const
24975 {
24976     CRITICAL_BLOCK(cs_wallet)
24977     {
24978         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
24979         if (mi != mapWallet.end())
24980         {
24981             const CWalletTx& prev = (*mi).second;
24982             if (txin.prevout.n < prev.vout.size())
24983                 if (IsMine(prev.vout[txin.prevout.n]))
24984                     return prev.vout[txin.prevout.n].nValue;
24985         }
24986     }
24987     return 0;
24988 }
24989 
24990 int64 CWalletTx::GetTxTime() const
24991 {
24992     return nTimeReceived;
24993 }
24994 
24995 int CWalletTx::GetRequestCount() const
24996 {
24997     // Returns -1 if it wasn't being tracked
24998     int nRequests = -1;
24999     CRITICAL_BLOCK(pwallet->cs_wallet)
25000     {
25001         if (IsCoinBase())
25002         {
25003             // Generated block
25004             if (hashBlock != 0)
25005             {
25006                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
25007                 if (mi != pwallet->mapRequestCount.end())
25008                     nRequests = (*mi).second;
25009             }
25010         }
25011         else
25012         {
25013             // Did anyone request this transaction?
25014             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
25015             if (mi != pwallet->mapRequestCount.end())
25016             {
25017                 nRequests = (*mi).second;
25018 
25019                 // How about the block it's in?
25020                 if (nRequests == 0 && hashBlock != 0)
25021                 {
25022                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
25023                     if (mi != pwallet->mapRequestCount.end())
25024                         nRequests = (*mi).second;
25025                     else
25026                         nRequests = 1; // If it's in someone else's block it must have got out
25027                 }
25028             }
25029         }
25030     }
25031     return nRequests;
25032 }
25033 
25034 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
25035                            list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
25036 {
25037     nGeneratedImmature = nGeneratedMature = nFee = 0;
25038     listReceived.clear();
25039     listSent.clear();
25040     strSentAccount = strFromAccount;
25041 
25042     if (IsCoinBase())
25043     {
25044         if (GetBlocksToMaturity() > 0)
25045             nGeneratedImmature = pwallet->GetCredit(*this);
25046         else
25047             nGeneratedMature = GetCredit();
25048         return;
25049     }
25050 
25051     // Compute fee:
25052     int64 nDebit = GetDebit();
25053     if (nDebit > 0) // debit>0 means we signed/sent this transaction
25054     {
25055         int64 nValueOut = GetValueOut();
25056         nFee = nDebit - nValueOut;
25057     }
25058 
25059     // Sent/received.  Standard client will never generate a send-to-multiple-recipients,
25060     // but non-standard clients might (so return a list of address/amount pairs)
25061     BOOST_FOREACH(const CTxOut& txout, vout)
25062     {
25063         CBitcoinAddress address;
25064         vector<unsigned char> vchPubKey;
25065         if (!ExtractAddress(txout.scriptPubKey, NULL, address))
25066         {
25067             printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
25068                    this->GetHash().ToString().c_str());
25069             address = " unknown ";
25070         }
25071 
25072         // Don't report 'change' txouts
25073         if (nDebit > 0 && pwallet->IsChange(txout))
25074             continue;
25075 
25076         if (nDebit > 0)
25077             listSent.push_back(make_pair(address, txout.nValue));
25078 
25079         if (pwallet->IsMine(txout))
25080             listReceived.push_back(make_pair(address, txout.nValue));
25081     }
25082 
25083 }
25084 
25085 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived, 
25086                                   int64& nSent, int64& nFee) const
25087 {
25088     nGenerated = nReceived = nSent = nFee = 0;
25089 
25090     int64 allGeneratedImmature, allGeneratedMature, allFee;
25091     allGeneratedImmature = allGeneratedMature = allFee = 0;
25092     string strSentAccount;
25093     list<pair<CBitcoinAddress, int64> > listReceived;
25094     list<pair<CBitcoinAddress, int64> > listSent;
25095     GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
25096 
25097     if (strAccount == "")
25098         nGenerated = allGeneratedMature;
25099     if (strAccount == strSentAccount)
25100     {
25101         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
25102             nSent += s.second;
25103         nFee = allFee;
25104     }
25105     CRITICAL_BLOCK(pwallet->cs_wallet)
25106     {
25107         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
25108         {
25109             if (pwallet->mapAddressBook.count(r.first))
25110             {
25111                 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
25112                 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
25113                     nReceived += r.second;
25114             }
25115             else if (strAccount.empty())
25116             {
25117                 nReceived += r.second;
25118             }
25119         }
25120     }
25121 }
25122 
25123 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
25124 {
25125     vtxPrev.clear();
25126 
25127     const int COPY_DEPTH = 3;
25128     if (SetMerkleBranch() < COPY_DEPTH)
25129     {
25130         vector<uint256> vWorkQueue;
25131         BOOST_FOREACH(const CTxIn& txin, vin)
25132             vWorkQueue.push_back(txin.prevout.hash);
25133 
25134         // This critsect is OK because txdb is already open
25135         CRITICAL_BLOCK(pwallet->cs_wallet)
25136         {
25137             map<uint256, const CMerkleTx*> mapWalletPrev;
25138             set<uint256> setAlreadyDone;
25139             for (int i = 0; i < vWorkQueue.size(); i++)
25140             {
25141                 uint256 hash = vWorkQueue[i];
25142                 if (setAlreadyDone.count(hash))
25143                     continue;
25144                 setAlreadyDone.insert(hash);
25145 
25146                 CMerkleTx tx;
25147                 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
25148                 if (mi != pwallet->mapWallet.end())
25149                 {
25150                     tx = (*mi).second;
25151                     BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
25152                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
25153                 }
25154                 else if (mapWalletPrev.count(hash))
25155                 {
25156                     tx = *mapWalletPrev[hash];
25157                 }
25158                 else if (!fClient && txdb.ReadDiskTx(hash, tx))
25159                 {
25160                     ;
25161                 }
25162                 else
25163                 {
25164                     printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
25165                     continue;
25166                 }
25167 
25168                 int nDepth = tx.SetMerkleBranch();
25169                 vtxPrev.push_back(tx);
25170 
25171                 if (nDepth < COPY_DEPTH)
25172                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
25173                         vWorkQueue.push_back(txin.prevout.hash);
25174             }
25175         }
25176     }
25177 
25178     reverse(vtxPrev.begin(), vtxPrev.end());
25179 }
25180 
25181 bool CWalletTx::WriteToDisk()
25182 {
25183     return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
25184 }
25185 
25186 // Scan the block chain (starting in pindexStart) for transactions
25187 // from or to us. If fUpdate is true, found transactions that already
25188 // exist in the wallet will be updated.
25189 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
25190 {
25191     int ret = 0;
25192 
25193     CBlockIndex* pindex = pindexStart;
25194     CRITICAL_BLOCK(cs_wallet)
25195     {
25196         while (pindex)
25197         {
25198             CBlock block;
25199             block.ReadFromDisk(pindex, true);
25200             BOOST_FOREACH(CTransaction& tx, block.vtx)
25201             {
25202                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
25203                     ret++;
25204             }
25205             pindex = pindex->pnext;
25206         }
25207     }
25208     return ret;
25209 }
25210 
25211 void CWallet::ReacceptWalletTransactions()
25212 {
25213     CTxDB txdb("r");
25214     bool fRepeat = true;
25215     while (fRepeat) CRITICAL_BLOCK(cs_wallet)
25216     {
25217         fRepeat = false;
25218         vector<CDiskTxPos> vMissingTx;
25219         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
25220         {
25221             CWalletTx& wtx = item.second;
25222             if (wtx.IsCoinBase() && wtx.IsSpent(0))
25223                 continue;
25224 
25225             CTxIndex txindex;
25226             bool fUpdated = false;
25227             if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
25228             {
25229                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
25230                 if (txindex.vSpent.size() != wtx.vout.size())
25231                 {
25232                     printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
25233                     continue;
25234                 }
25235                 for (int i = 0; i < txindex.vSpent.size(); i++)
25236                 {
25237                     if (wtx.IsSpent(i))
25238                         continue;
25239                     if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
25240                     {
25241                         wtx.MarkSpent(i);
25242                         fUpdated = true;
25243                         vMissingTx.push_back(txindex.vSpent[i]);
25244                     }
25245                 }
25246                 if (fUpdated)
25247                 {
25248                     printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
25249                     wtx.MarkDirty();
25250                     wtx.WriteToDisk();
25251                 }
25252             }
25253             else
25254             {
25255                 // Reaccept any txes of ours that aren't already in a block
25256                 if (!wtx.IsCoinBase())
25257                     wtx.AcceptWalletTransaction(txdb, false);
25258             }
25259         }
25260         if (!vMissingTx.empty())
25261         {
25262             // TODO: optimize this to scan just part of the block chain?
25263             if (ScanForWalletTransactions(pindexGenesisBlock))
25264                 fRepeat = true;  // Found missing transactions: re-do Reaccept.
25265         }
25266     }
25267 }
25268 
25269 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
25270 {
25271     BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
25272     {
25273         if (!tx.IsCoinBase())
25274         {
25275             uint256 hash = tx.GetHash();
25276             if (!txdb.ContainsTx(hash))
25277                 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
25278         }
25279     }
25280     if (!IsCoinBase())
25281     {
25282         uint256 hash = GetHash();
25283         if (!txdb.ContainsTx(hash))
25284         {
25285             printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
25286             RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
25287         }
25288     }
25289 }
25290 
25291 void CWalletTx::RelayWalletTransaction()
25292 {
25293    CTxDB txdb("r");
25294    RelayWalletTransaction(txdb);
25295 }
25296 
25297 void CWallet::ResendWalletTransactions()
25298 {
25299     // Do this infrequently and randomly to avoid giving away
25300     // that these are our transactions.
25301     static int64 nNextTime;
25302     if (GetTime() < nNextTime)
25303         return;
25304     bool fFirst = (nNextTime == 0);
25305     nNextTime = GetTime() + GetRand(30 * 60);
25306     if (fFirst)
25307         return;
25308 
25309     // Only do it if there's been a new block since last time
25310     static int64 nLastTime;
25311     if (nTimeBestReceived < nLastTime)
25312         return;
25313     nLastTime = GetTime();
25314 
25315     // Rebroadcast any of our txes that aren't in a block yet
25316     printf("ResendWalletTransactions()\n");
25317     CTxDB txdb("r");
25318     CRITICAL_BLOCK(cs_wallet)
25319     {
25320         // Sort them in chronological order
25321         multimap<unsigned int, CWalletTx*> mapSorted;
25322         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
25323         {
25324             CWalletTx& wtx = item.second;
25325             // Don't rebroadcast until it's had plenty of time that
25326             // it should have gotten in already by now.
25327             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
25328                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
25329         }
25330         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
25331         {
25332             CWalletTx& wtx = *item.second;
25333             wtx.RelayWalletTransaction(txdb);
25334         }
25335     }
25336 }
25337 
25338 
25339 
25340 
25341 
25342 
25343 //////////////////////////////////////////////////////////////////////////////
25344 //
25345 // Actions
25346 //
25347 
25348 
25349 int64 CWallet::GetBalance() const
25350 {
25351     int64 nTotal = 0;
25352     CRITICAL_BLOCK(cs_wallet)
25353     {
25354         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
25355         {
25356             const CWalletTx* pcoin = &(*it).second;
25357             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
25358                 continue;
25359             nTotal += pcoin->GetAvailableCredit();
25360         }
25361     }
25362 
25363     return nTotal;
25364 }
25365 
25366 int64 CWallet::GetUnconfirmedBalance() const
25367 {
25368     int64 nTotal = 0;
25369     CRITICAL_BLOCK(cs_wallet)
25370     {
25371         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
25372         {
25373             const CWalletTx* pcoin = &(*it).second;
25374             if (pcoin->IsFinal() && pcoin->IsConfirmed())
25375                 continue;
25376             nTotal += pcoin->GetAvailableCredit();
25377         }
25378     }
25379     return nTotal;
25380 }
25381 
25382 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
25383 {
25384     setCoinsRet.clear();
25385     nValueRet = 0;
25386 
25387     // List of values less than target
25388     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
25389     coinLowestLarger.first = INT64_MAX;
25390     coinLowestLarger.second.first = NULL;
25391     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
25392     int64 nTotalLower = 0;
25393 
25394     CRITICAL_BLOCK(cs_wallet)
25395     {
25396        vector<const CWalletTx*> vCoins;
25397        vCoins.reserve(mapWallet.size());
25398        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
25399            vCoins.push_back(&(*it).second);
25400        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
25401 
25402        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
25403        {
25404             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
25405                 continue;
25406 
25407             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
25408                 continue;
25409 
25410             int nDepth = pcoin->GetDepthInMainChain();
25411             if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
25412                 continue;
25413 
25414             for (int i = 0; i < pcoin->vout.size(); i++)
25415             {
25416                 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
25417                     continue;
25418 
25419                 int64 n = pcoin->vout[i].nValue;
25420 
25421                 if (n <= 0)
25422                     continue;
25423 
25424                 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
25425 
25426                 if (n == nTargetValue)
25427                 {
25428                     setCoinsRet.insert(coin.second);
25429                     nValueRet += coin.first;
25430                     return true;
25431                 }
25432                 else if (n < nTargetValue + CENT)
25433                 {
25434                     vValue.push_back(coin);
25435                     nTotalLower += n;
25436                 }
25437                 else if (n < coinLowestLarger.first)
25438                 {
25439                     coinLowestLarger = coin;
25440                 }
25441             }
25442         }
25443     }
25444 
25445     if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
25446     {
25447         for (int i = 0; i < vValue.size(); ++i)
25448         {
25449             setCoinsRet.insert(vValue[i].second);
25450             nValueRet += vValue[i].first;
25451         }
25452         return true;
25453     }
25454 
25455     if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
25456     {
25457         if (coinLowestLarger.second.first == NULL)
25458             return false;
25459         setCoinsRet.insert(coinLowestLarger.second);
25460         nValueRet += coinLowestLarger.first;
25461         return true;
25462     }
25463 
25464     if (nTotalLower >= nTargetValue + CENT)
25465         nTargetValue += CENT;
25466 
25467     // Solve subset sum by stochastic approximation
25468     sort(vValue.rbegin(), vValue.rend());
25469     vector<char> vfIncluded;
25470     vector<char> vfBest(vValue.size(), true);
25471     int64 nBest = nTotalLower;
25472 
25473     for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
25474     {
25475         vfIncluded.assign(vValue.size(), false);
25476         int64 nTotal = 0;
25477         bool fReachedTarget = false;
25478         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
25479         {
25480             for (int i = 0; i < vValue.size(); i++)
25481             {
25482                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
25483                 {
25484                     nTotal += vValue[i].first;
25485                     vfIncluded[i] = true;
25486                     if (nTotal >= nTargetValue)
25487                     {
25488                         fReachedTarget = true;
25489                         if (nTotal < nBest)
25490                         {
25491                             nBest = nTotal;
25492                             vfBest = vfIncluded;
25493                         }
25494                         nTotal -= vValue[i].first;
25495                         vfIncluded[i] = false;
25496                     }
25497                 }
25498             }
25499         }
25500     }
25501 
25502     // If the next larger is still closer, return it
25503     if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
25504     {
25505         setCoinsRet.insert(coinLowestLarger.second);
25506         nValueRet += coinLowestLarger.first;
25507     }
25508     else {
25509         for (int i = 0; i < vValue.size(); i++)
25510             if (vfBest[i])
25511             {
25512                 setCoinsRet.insert(vValue[i].second);
25513                 nValueRet += vValue[i].first;
25514             }
25515 
25516         //// debug print
25517         printf("SelectCoins() best subset: ");
25518         for (int i = 0; i < vValue.size(); i++)
25519             if (vfBest[i])
25520                 printf("%s ", FormatMoney(vValue[i].first).c_str());
25521         printf("total %s\n", FormatMoney(nBest).c_str());
25522     }
25523 
25524     return true;
25525 }
25526 
25527 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
25528 {
25529     return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
25530             SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
25531             SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
25532 }
25533 
25534 
25535 
25536 
25537 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
25538 {
25539     int64 nValue = 0;
25540     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
25541     {
25542         if (nValue < 0)
25543             return false;
25544         nValue += s.second;
25545     }
25546     if (vecSend.empty() || nValue < 0)
25547         return false;
25548 
25549     wtxNew.pwallet = this;
25550 
25551     CRITICAL_BLOCK(cs_main)
25552     CRITICAL_BLOCK(cs_wallet)
25553     {
25554         // txdb must be opened before the mapWallet lock
25555         CTxDB txdb("r");
25556         {
25557             nFeeRet = nTransactionFee;
25558             loop
25559             {
25560                 wtxNew.vin.clear();
25561                 wtxNew.vout.clear();
25562                 wtxNew.fFromMe = true;
25563 
25564                 int64 nTotalValue = nValue + nFeeRet;
25565                 double dPriority = 0;
25566                 // vouts to the payees
25567                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
25568                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
25569 
25570                 // Choose coins to use
25571                 set<pair<const CWalletTx*,unsigned int> > setCoins;
25572                 int64 nValueIn = 0;
25573                 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
25574                     return false;
25575                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
25576                 {
25577                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
25578                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
25579                 }
25580 
25581                 int64 nChange = nValueIn - nValue - nFeeRet;
25582                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
25583                 // or until nChange becomes zero
25584                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
25585                 {
25586                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
25587                     nChange -= nMoveToFee;
25588                     nFeeRet += nMoveToFee;
25589                 }
25590 
25591                 if (nChange > 0)
25592                 {
25593                     // Note: We use a new key here to keep it from being obvious which side is the change.
25594                     //  The drawback is that by not reusing a previous key, the change may be lost if a
25595                     //  backup is restored, if the backup doesn't have the new private key for the change.
25596                     //  If we reused the old key, it would be possible to add code to look for and
25597                     //  rediscover unknown transactions that were written with keys of ours to recover
25598                     //  post-backup change.
25599 
25600                     // Reserve a new key pair from key pool
25601                     vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
25602                     // assert(mapKeys.count(vchPubKey));
25603 
25604                     // Fill a vout to ourself, using same address type as the payment
25605                     CScript scriptChange;
25606                     if (vecSend[0].first.GetBitcoinAddress().IsValid())
25607                         scriptChange.SetBitcoinAddress(vchPubKey);
25608                     else
25609                         scriptChange << vchPubKey << OP_CHECKSIG;
25610 
25611                     // Insert change txn at random position:
25612                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
25613                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
25614                 }
25615                 else
25616                     reservekey.ReturnKey();
25617 
25618                 // Fill vin
25619                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
25620                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
25621 
25622                 // Sign
25623                 int nIn = 0;
25624                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
25625                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
25626                         return false;
25627 
25628                 // Limit size
25629                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
25630                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
25631                     return false;
25632                 dPriority /= nBytes;
25633 
25634                 // Check that enough fee is included
25635                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
25636                 bool fAllowFree = CTransaction::AllowFree(dPriority);
25637                 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
25638                 if (nFeeRet < max(nPayFee, nMinFee))
25639                 {
25640                     nFeeRet = max(nPayFee, nMinFee);
25641                     continue;
25642                 }
25643 
25644                 // Fill vtxPrev by copying from previous transactions vtxPrev
25645                 wtxNew.AddSupportingTransactions(txdb);
25646                 wtxNew.fTimeReceivedIsTxTime = true;
25647 
25648                 break;
25649             }
25650         }
25651     }
25652     return true;
25653 }
25654 
25655 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
25656 {
25657     vector< pair<CScript, int64> > vecSend;
25658     vecSend.push_back(make_pair(scriptPubKey, nValue));
25659     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
25660 }
25661 
25662 // Call after CreateTransaction unless you want to abort
25663 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
25664 {
25665     CRITICAL_BLOCK(cs_main)
25666     CRITICAL_BLOCK(cs_wallet)
25667     {
25668         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
25669         {
25670             // This is only to keep the database open to defeat the auto-flush for the
25671             // duration of this scope.  This is the only place where this optimization
25672             // maybe makes sense; please don't do it anywhere else.
25673             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
25674 
25675             // Take key pair from key pool so it won't be used again
25676             reservekey.KeepKey();
25677 
25678             // Add tx to wallet, because if it has change it's also ours,
25679             // otherwise just for transaction history.
25680             AddToWallet(wtxNew);
25681 
25682             // Mark old coins as spent
25683             set<CWalletTx*> setCoins;
25684             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
25685             {
25686                 CWalletTx &coin = mapWallet[txin.prevout.hash];
25687                 coin.pwallet = this;
25688                 coin.MarkSpent(txin.prevout.n);
25689                 coin.WriteToDisk();
25690                 vWalletUpdated.push_back(coin.GetHash());
25691             }
25692 
25693             if (fFileBacked)
25694                 delete pwalletdb;
25695         }
25696 
25697         // Track how many getdata requests our transaction gets
25698         mapRequestCount[wtxNew.GetHash()] = 0;
25699 
25700         // Broadcast
25701         if (!wtxNew.AcceptToMemoryPool())
25702         {
25703             // This must not fail. The transaction has already been signed and recorded.
25704             printf("CommitTransaction() : Error: Transaction not valid");
25705             return false;
25706         }
25707         wtxNew.RelayWalletTransaction();
25708     }
25709     MainFrameRepaint();
25710     return true;
25711 }
25712 
25713 
25714 
25715 
25716 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
25717 {
25718     CReserveKey reservekey(this);
25719     int64 nFeeRequired;
25720 
25721     if (IsLocked())
25722     {
25723         string strError = _("Error: Wallet locked, unable to create transaction  ");
25724         printf("SendMoney() : %s", strError.c_str());
25725         return strError;
25726     }
25727     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
25728     {
25729         string strError;
25730         if (nValue + nFeeRequired > GetBalance())
25731             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());
25732         else
25733             strError = _("Error: Transaction creation failed  ");
25734         printf("SendMoney() : %s", strError.c_str());
25735         return strError;
25736     }
25737 
25738     if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
25739         return "ABORTED";
25740 
25741     if (!CommitTransaction(wtxNew, reservekey))
25742         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.");
25743 
25744     MainFrameRepaint();
25745     return "";
25746 }
25747 
25748 
25749 
25750 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
25751 {
25752     // Check amount
25753     if (nValue <= 0)
25754         return _("Invalid amount");
25755     if (nValue + nTransactionFee > GetBalance())
25756         return _("Insufficient funds");
25757 
25758     // Parse bitcoin address
25759     CScript scriptPubKey;
25760     scriptPubKey.SetBitcoinAddress(address);
25761 
25762     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
25763 }
25764 
25765 
25766 
25767 
25768 int CWallet::LoadWallet(bool& fFirstRunRet)
25769 {
25770     if (!fFileBacked)
25771         return false;
25772     fFirstRunRet = false;
25773     int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
25774     if (nLoadWalletRet == DB_NEED_REWRITE)
25775     {
25776         if (CDB::Rewrite(strWalletFile, "\x04pool"))
25777         {
25778             setKeyPool.clear();
25779             // Note: can't top-up keypool here, because wallet is locked.
25780             // User will be prompted to unlock wallet the next operation
25781             // the requires a new key.
25782         }
25783         nLoadWalletRet = DB_NEED_REWRITE;
25784     }
25785 
25786     if (nLoadWalletRet != DB_LOAD_OK)
25787         return nLoadWalletRet;
25788     fFirstRunRet = vchDefaultKey.empty();
25789 
25790     if (!HaveKey(Hash160(vchDefaultKey)))
25791     {
25792         // Create new keyUser and set as default key
25793         RandAddSeedPerfmon();
25794 
25795         std::vector<unsigned char> newDefaultKey;
25796         if (!GetKeyFromPool(newDefaultKey, false))
25797             return DB_LOAD_FAIL;
25798         SetDefaultKey(newDefaultKey);
25799         if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
25800             return DB_LOAD_FAIL;
25801     }
25802 
25803     CreateThread(ThreadFlushWalletDB, &strWalletFile);
25804     return DB_LOAD_OK;
25805 }
25806 
25807 
25808 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
25809 {
25810     mapAddressBook[address] = strName;
25811     if (!fFileBacked)
25812         return false;
25813     return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
25814 }
25815 
25816 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
25817 {
25818     mapAddressBook.erase(address);
25819     if (!fFileBacked)
25820         return false;
25821     return CWalletDB(strWalletFile).EraseName(address.ToString());
25822 }
25823 
25824 
25825 void CWallet::PrintWallet(const CBlock& block)
25826 {
25827     CRITICAL_BLOCK(cs_wallet)
25828     {
25829         if (mapWallet.count(block.vtx[0].GetHash()))
25830         {
25831             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
25832             printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
25833         }
25834     }
25835     printf("\n");
25836 }
25837 
25838 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
25839 {
25840     CRITICAL_BLOCK(cs_wallet)
25841     {
25842         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
25843         if (mi != mapWallet.end())
25844         {
25845             wtx = (*mi).second;
25846             return true;
25847         }
25848     }
25849     return false;
25850 }
25851 
25852 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
25853 {
25854     if (fFileBacked)
25855     {
25856         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
25857             return false;
25858     }
25859     vchDefaultKey = vchPubKey;
25860     return true;
25861 }
25862 
25863 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
25864 {
25865     if (!pwallet->fFileBacked)
25866         return false;
25867     strWalletFileOut = pwallet->strWalletFile;
25868     return true;
25869 }
25870 
25871 //
25872 // Mark old keypool keys as used,
25873 // and generate all new keys
25874 //
25875 bool CWallet::NewKeyPool()
25876 {
25877     CRITICAL_BLOCK(cs_wallet)
25878     {
25879         CWalletDB walletdb(strWalletFile);
25880         BOOST_FOREACH(int64 nIndex, setKeyPool)
25881             walletdb.ErasePool(nIndex);
25882         setKeyPool.clear();
25883 
25884         if (IsLocked())
25885             return false;
25886 
25887         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
25888         for (int i = 0; i < nKeys; i++)
25889         {
25890             int64 nIndex = i+1;
25891             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
25892             setKeyPool.insert(nIndex);
25893         }
25894         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
25895     }
25896     return true;
25897 }
25898 
25899 bool CWallet::TopUpKeyPool()
25900 {
25901     CRITICAL_BLOCK(cs_wallet)
25902     {
25903         if (IsLocked())
25904             return false;
25905 
25906         CWalletDB walletdb(strWalletFile);
25907 
25908         // Top up key pool
25909         int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
25910         while (setKeyPool.size() < nTargetSize+1)
25911         {
25912             int64 nEnd = 1;
25913             if (!setKeyPool.empty())
25914                 nEnd = *(--setKeyPool.end()) + 1;
25915             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
25916                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
25917             setKeyPool.insert(nEnd);
25918             printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
25919         }
25920     }
25921     return true;
25922 }
25923 
25924 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
25925 {
25926     nIndex = -1;
25927     keypool.vchPubKey.clear();
25928     CRITICAL_BLOCK(cs_wallet)
25929     {
25930         if (!IsLocked())
25931             TopUpKeyPool();
25932 
25933         // Get the oldest key
25934         if(setKeyPool.empty())
25935             return;
25936 
25937         CWalletDB walletdb(strWalletFile);
25938 
25939         nIndex = *(setKeyPool.begin());
25940         setKeyPool.erase(setKeyPool.begin());
25941         if (!walletdb.ReadPool(nIndex, keypool))
25942             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
25943         if (!HaveKey(Hash160(keypool.vchPubKey)))
25944             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
25945         assert(!keypool.vchPubKey.empty());
25946         printf("keypool reserve %"PRI64d"\n", nIndex);
25947     }
25948 }
25949 
25950 void CWallet::KeepKey(int64 nIndex)
25951 {
25952     // Remove from key pool
25953     if (fFileBacked)
25954     {
25955         CWalletDB walletdb(strWalletFile);
25956         walletdb.ErasePool(nIndex);
25957     }
25958     printf("keypool keep %"PRI64d"\n", nIndex);
25959 }
25960 
25961 void CWallet::ReturnKey(int64 nIndex)
25962 {
25963     // Return to key pool
25964     CRITICAL_BLOCK(cs_wallet)
25965         setKeyPool.insert(nIndex);
25966     printf("keypool return %"PRI64d"\n", nIndex);
25967 }
25968 
25969 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
25970 {
25971     int64 nIndex = 0;
25972     CKeyPool keypool;
25973     CRITICAL_BLOCK(cs_wallet)
25974     {
25975         ReserveKeyFromKeyPool(nIndex, keypool);
25976         if (nIndex == -1)
25977         {
25978             if (fAllowReuse && !vchDefaultKey.empty())
25979             {
25980                 result = vchDefaultKey;
25981                 return true;
25982             }
25983             if (IsLocked()) return false;
25984             result = GenerateNewKey();
25985             return true;
25986         }
25987         KeepKey(nIndex);
25988         result = keypool.vchPubKey;
25989     }
25990     return true;
25991 }
25992 
25993 int64 CWallet::GetOldestKeyPoolTime()
25994 {
25995     int64 nIndex = 0;
25996     CKeyPool keypool;
25997     ReserveKeyFromKeyPool(nIndex, keypool);
25998     if (nIndex == -1)
25999         return GetTime();
26000     ReturnKey(nIndex);
26001     return keypool.nTime;
26002 }
26003 
26004 vector<unsigned char> CReserveKey::GetReservedKey()
26005 {
26006     if (nIndex == -1)
26007     {
26008         CKeyPool keypool;
26009         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
26010         if (nIndex != -1)
26011             vchPubKey = keypool.vchPubKey;
26012         else
26013         {
26014             printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
26015             vchPubKey = pwallet->vchDefaultKey;
26016         }
26017     }
26018     assert(!vchPubKey.empty());
26019     return vchPubKey;
26020 }
26021 
26022 void CReserveKey::KeepKey()
26023 {
26024     if (nIndex != -1)
26025         pwallet->KeepKey(nIndex);
26026     nIndex = -1;
26027     vchPubKey.clear();
26028 }
26029 
26030 void CReserveKey::ReturnKey()
26031 {
26032     if (nIndex != -1)
26033         pwallet->ReturnKey(nIndex);
26034     nIndex = -1;
26035     vchPubKey.clear();
26036 }
26037