CWallet class
authorPieter Wuille <pieter.wuille@gmail.com>
Wed, 1 Jun 2011 16:28:20 +0000 (18:28 +0200)
committerPieter Wuille <pieter.wuille@gmail.com>
Wed, 15 Jun 2011 09:05:55 +0000 (11:05 +0200)
* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore.
* A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around.
* Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter
* CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions.
* Some code was moved from CWalletDB to CWallet, such as handling of reserve keys.
* Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument.
* The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable.
* Functions in main.cpp and db.cpp that are not used by other modules are marked static.
* The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.

15 files changed:
src/db.cpp
src/db.h
src/init.cpp
src/init.h
src/keystore.cpp
src/keystore.h
src/main.cpp
src/main.h
src/net.cpp
src/rpc.cpp
src/script.cpp
src/script.h
src/ui.cpp
src/wallet.cpp
src/wallet.h

index 30e4bb0..d5405d7 100644 (file)
@@ -10,8 +10,6 @@
 using namespace std;
 using namespace boost;
 
-void ThreadFlushWalletDB(void* parg);
-
 
 unsigned int nWalletDBUpdated;
 uint64 nAccountingEntryNumber = 0;
@@ -150,7 +148,7 @@ void CDB::Close()
         --mapFileUseCount[strFile];
 }
 
-void CloseDb(const string& strFile)
+void static CloseDb(const string& strFile)
 {
     CRITICAL_BLOCK(cs_db)
     {
@@ -359,7 +357,7 @@ bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
     return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
 }
 
-CBlockIndex* InsertBlockIndex(uint256 hash)
+CBlockIndex static * InsertBlockIndex(uint256 hash)
 {
     if (hash == 0)
         return NULL;
@@ -584,6 +582,20 @@ bool LoadAddresses()
 // CWalletDB
 //
 
+bool CWalletDB::WriteName(const string& strAddress, const string& strName)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("name"), strAddress), strName);
+}
+
+bool CWalletDB::EraseName(const string& strAddress)
+{
+    // This should only be used for sending addresses, never for receiving addresses,
+    // receiving addresses must always have an address book entry if they're not change return.
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("name"), strAddress));
+}
+
 bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
 {
     account.SetNull();
@@ -657,9 +669,9 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
 }
 
 
-bool CWalletDB::LoadWallet()
+bool CWalletDB::LoadWallet(CWallet* pwallet)
 {
-    vchDefaultKey.clear();
+    pwallet->vchDefaultKey.clear();
     int nFileVersion = 0;
     vector<uint256> vWalletUpgrade;
 
@@ -671,8 +683,8 @@ bool CWalletDB::LoadWallet()
 #endif
 
     //// todo: shouldn't we catch exceptions and try to recover and continue?
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(pwallet->cs_mapWallet)
+    CRITICAL_BLOCK(pwallet->cs_mapKeys)
     {
         // Get cursor
         Dbc* pcursor = GetCursor();
@@ -699,14 +711,15 @@ bool CWalletDB::LoadWallet()
             {
                 string strAddress;
                 ssKey >> strAddress;
-                ssValue >> mapAddressBook[strAddress];
+                ssValue >> pwallet->mapAddressBook[strAddress];
             }
             else if (strType == "tx")
             {
                 uint256 hash;
                 ssKey >> hash;
-                CWalletTx& wtx = mapWallet[hash];
+                CWalletTx& wtx = pwallet->mapWallet[hash];
                 ssValue >> wtx;
+                wtx.pwallet = pwallet;
 
                 if (wtx.GetHash() != hash)
                     printf("Error in wallet.dat, hash mismatch\n");
@@ -757,18 +770,18 @@ bool CWalletDB::LoadWallet()
                 else
                     ssValue >> wkey;
 
-                mapKeys[vchPubKey] = wkey.vchPrivKey;
+                pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey;
                 mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
             }
             else if (strType == "defaultkey")
             {
-                ssValue >> vchDefaultKey;
+                ssValue >> pwallet->vchDefaultKey;
             }
             else if (strType == "pool")
             {
                 int64 nIndex;
                 ssKey >> nIndex;
-                setKeyPool.insert(nIndex);
+                pwallet->setKeyPool.insert(nIndex);
             }
             else if (strType == "version")
             {
@@ -800,7 +813,7 @@ bool CWalletDB::LoadWallet()
     }
 
     BOOST_FOREACH(uint256 hash, vWalletUpgrade)
-        WriteTx(hash, mapWallet[hash]);
+        WriteTx(hash, pwallet->mapWallet[hash]);
 
     printf("nFileVersion = %d\n", nFileVersion);
     printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
@@ -830,6 +843,7 @@ bool CWalletDB::LoadWallet()
 
 void ThreadFlushWalletDB(void* parg)
 {
+    const string& strFile = ((const string*)parg)[0];
     static bool fOneThread;
     if (fOneThread)
         return;
@@ -865,7 +879,6 @@ void ThreadFlushWalletDB(void* parg)
 
                 if (nRefCount == 0 && !fShutdown)
                 {
-                    string strFile = "wallet.dat";
                     map<string, int>::iterator mi = mapFileUseCount.find(strFile);
                     if (mi != mapFileUseCount.end())
                     {
@@ -888,26 +901,27 @@ void ThreadFlushWalletDB(void* parg)
     }
 }
 
-void BackupWallet(const string& strDest)
+bool BackupWallet(const CWallet& wallet, const string& strDest)
 {
+    if (!wallet.fFileBacked)
+        return false;
     while (!fShutdown)
     {
         CRITICAL_BLOCK(cs_db)
         {
-            const string strFile = "wallet.dat";
-            if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
+            if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
             {
                 // Flush log data to the dat file
-                CloseDb(strFile);
+                CloseDb(wallet.strWalletFile);
                 dbenv.txn_checkpoint(0, 0, 0);
-                dbenv.lsn_reset(strFile.c_str(), 0);
-                mapFileUseCount.erase(strFile);
+                dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
+                mapFileUseCount.erase(wallet.strWalletFile);
 
                 // Copy wallet.dat
-                filesystem::path pathSrc(GetDataDir() + "/" + strFile);
+                filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
                 filesystem::path pathDest(strDest);
                 if (filesystem::is_directory(pathDest))
-                    pathDest = pathDest / strFile;
+                    pathDest = pathDest / wallet.strWalletFile;
 #if BOOST_VERSION >= 104000
                 filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
 #else
@@ -915,11 +929,10 @@ void BackupWallet(const string& strDest)
 #endif
                 printf("copied wallet.dat to %s\n", pathDest.string().c_str());
 
-                return;
+                return true;
             }
         }
         Sleep(100);
     }
+    return false;
 }
-
-
index 5779837..b89b34e 100644 (file)
--- a/src/db.h
+++ b/src/db.h
 
 #include <db_cxx.h>
 
-class CTransaction;
 class CTxIndex;
 class CDiskBlockIndex;
 class CDiskTxPos;
 class COutPoint;
-class CUser;
-class CReview;
 class CAddress;
 class CWalletTx;
+class CWallet;
 class CAccount;
 class CAccountingEntry;
 class CBlockLocator;
 
-extern std::vector<unsigned char> vchDefaultKey;
-extern bool fClient;
-extern int nBestHeight;
-
 
 extern unsigned int nWalletDBUpdated;
 extern DbEnv dbenv;
 
 
 extern void DBFlush(bool fShutdown);
-extern std::vector<unsigned char> GetKeyFromKeyPool();
-extern int64 GetOldestKeyPoolTime();
-extern void ThreadFlushWalletDB(void* parg);
-
+void ThreadFlushWalletDB(void* parg);
+bool BackupWallet(const CWallet& wallet, const std::string& strDest);
 
 
 
@@ -321,9 +313,6 @@ bool LoadAddresses();
 
 
 
-
-
-
 class CKeyPool
 {
 public:
@@ -356,7 +345,7 @@ public:
 class CWalletDB : public CDB
 {
 public:
-    CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
+    CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
     {
     }
 private:
@@ -369,23 +358,9 @@ public:
         return Read(std::make_pair(std::string("name"), strAddress), strName);
     }
 
-    bool WriteName(const std::string& strAddress, const std::string& strName)
-    {
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            mapAddressBook[strAddress] = strName;
-        nWalletDBUpdated++;
-        return Write(std::make_pair(std::string("name"), strAddress), strName);
-    }
+    bool WriteName(const std::string& strAddress, const std::string& strName);
 
-    bool EraseName(const std::string& strAddress)
-    {
-        // This should only be used for sending addresses, never for receiving addresses,
-        // receiving addresses must always have an address book entry if they're not change return.
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            mapAddressBook.erase(strAddress);
-        nWalletDBUpdated++;
-        return Erase(std::make_pair(std::string("name"), strAddress));
-    }
+    bool EraseName(const std::string& strAddress);
 
     bool ReadTx(uint256 hash, CWalletTx& wtx)
     {
@@ -435,11 +410,27 @@ public:
 
     bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
     {
-        vchDefaultKey = vchPubKey;
         nWalletDBUpdated++;
         return Write(std::string("defaultkey"), vchPubKey);
     }
 
+    bool ReadPool(int64 nPool, CKeyPool& keypool)
+    {
+        return Read(std::make_pair(std::string("pool"), nPool), keypool);
+    }
+
+    bool WritePool(int64 nPool, const CKeyPool& keypool)
+    {
+        nWalletDBUpdated++;
+        return Write(std::make_pair(std::string("pool"), nPool), keypool);
+    }
+
+    bool ErasePool(int64 nPool)
+    {
+        nWalletDBUpdated++;
+        return Erase(std::make_pair(std::string("pool"), nPool));
+    }
+
     template<typename T>
     bool ReadSetting(const std::string& strKey, T& value)
     {
@@ -459,44 +450,7 @@ public:
     int64 GetAccountCreditDebit(const std::string& strAccount);
     void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
 
-    bool LoadWallet();
-protected:
-    void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
-    void KeepKey(int64 nIndex);
-    static void ReturnKey(int64 nIndex);
-    friend class CReserveKey;
-    friend std::vector<unsigned char> GetKeyFromKeyPool();
-    friend int64 GetOldestKeyPoolTime();
-};
-
-bool LoadWallet(bool& fFirstRunRet);
-void BackupWallet(const std::string& strDest);
-
-inline bool SetAddressBookName(const std::string& strAddress, const std::string& strName)
-{
-    return CWalletDB().WriteName(strAddress, strName);
-}
-
-class CReserveKey
-{
-protected:
-    int64 nIndex;
-    std::vector<unsigned char> vchPubKey;
-public:
-    CReserveKey()
-    {
-        nIndex = -1;
-    }
-
-    ~CReserveKey()
-    {
-        if (!fShutdown)
-            ReturnKey();
-    }
-
-    std::vector<unsigned char> GetReservedKey();
-    void KeepKey();
-    void ReturnKey();
+    bool LoadWallet(CWallet* pwallet);
 };
 
 #endif
index b683e66..62bf169 100644 (file)
@@ -13,6 +13,8 @@
 using namespace std;
 using namespace boost;
 
+CWallet* pwalletMain;
+
 //////////////////////////////////////////////////////////////////////////////
 //
 // Shutdown
@@ -45,6 +47,8 @@ void Shutdown(void* parg)
         StopNode();
         DBFlush(true);
         boost::filesystem::remove(GetPidFile());
+        UnregisterWallet(pwalletMain);
+        delete pwalletMain;
         CreateThread(ExitTimeout, NULL);
         Sleep(50);
         printf("Bitcoin exiting\n\n");
@@ -372,16 +376,19 @@ bool AppInit2(int argc, char* argv[])
     printf("Loading wallet...\n");
     nStart = GetTimeMillis();
     bool fFirstRun;
-    if (!LoadWallet(fFirstRun))
+    pwalletMain = new CWallet("wallet.dat");
+    if (!pwalletMain->LoadWallet(fFirstRun))
         strErrors += _("Error loading wallet.dat      \n");
     printf(" wallet      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
 
+    RegisterWallet(pwalletMain);
+
     CBlockIndex *pindexRescan = pindexBest;
     if (GetBoolArg("-rescan"))
         pindexRescan = pindexGenesisBlock;
     else
     {
-        CWalletDB walletdb;
+        CWalletDB walletdb("wallet.dat");
         CBlockLocator locator;
         if (walletdb.ReadBestBlock(locator))
             pindexRescan = locator.GetBlockIndex();
@@ -390,7 +397,7 @@ bool AppInit2(int argc, char* argv[])
     {
         printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
         nStart = GetTimeMillis();
-        ScanForWalletTransactions(pindexRescan, true);
+        pwalletMain->ScanForWalletTransactions(pindexRescan, true);
         printf(" rescan      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
     }
 
@@ -399,10 +406,11 @@ bool AppInit2(int argc, char* argv[])
         //// debug print
         printf("mapBlockIndex.size() = %d\n",   mapBlockIndex.size());
         printf("nBestHeight = %d\n",            nBestHeight);
-        printf("mapKeys.size() = %d\n",         mapKeys.size());
+        printf("mapKeys.size() = %d\n",         pwalletMain->mapKeys.size());
+        printf("setKeyPool.size() = %d\n",      pwalletMain->setKeyPool.size());
         printf("mapPubKeys.size() = %d\n",      mapPubKeys.size());
-        printf("mapWallet.size() = %d\n",       mapWallet.size());
-        printf("mapAddressBook.size() = %d\n",  mapAddressBook.size());
+        printf("mapWallet.size() = %d\n",       pwalletMain->mapWallet.size());
+        printf("mapAddressBook.size() = %d\n",  pwalletMain->mapAddressBook.size());
 
     if (!strErrors.empty())
     {
@@ -411,7 +419,7 @@ bool AppInit2(int argc, char* argv[])
     }
 
     // Add wallet transactions that aren't already in a block to mapTransactions
-    ReacceptWalletTransactions();
+    pwalletMain->ReacceptWalletTransactions();
 
     //
     // Parameters
index 61b2728..a02260c 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef BITCOIN_INIT_H
 #define BITCOIN_INIT_H
 
+extern CWallet* pwalletMain;
+
 void Shutdown(void* parg);
 bool AppInit(int argc, char* argv[]);
 bool AppInit2(int argc, char* argv[]);
index 51f39a5..7dd045f 100644 (file)
@@ -12,7 +12,7 @@
 // mapKeys
 //
 
-std::vector<unsigned char> GenerateNewKey()
+std::vector<unsigned char> CKeyStore::GenerateNewKey()
 {
     RandAddSeedPerfmon();
     CKey key;
@@ -22,12 +22,12 @@ std::vector<unsigned char> GenerateNewKey()
     return key.GetPubKey();
 }
 
-bool AddKey(const CKey& key)
+bool CKeyStore::AddKey(const CKey& key)
 {
     CRITICAL_BLOCK(cs_mapKeys)
     {
         mapKeys[key.GetPubKey()] = key.GetPrivKey();
         mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
     }
-    return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
 }
+
index 2f37ec5..3b6869b 100644 (file)
@@ -4,7 +4,23 @@
 #ifndef BITCOIN_KEYSTORE_H
 #define BITCOIN_KEYSTORE_H
 
-bool AddKey(const CKey& key);
-std::vector<unsigned char> GenerateNewKey();
+class CKeyStore
+{
+public:
+    std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
+    mutable CCriticalSection cs_mapKeys;
+    virtual bool AddKey(const CKey& key);
+    bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
+    {
+        return (mapKeys.count(vchPubKey) > 0);
+    }
+    CPrivKey GetPrivKey(const std::vector<unsigned char> &vchPubKey) const
+    {
+        std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
+        if (mi != mapKeys.end())
+            return (*mi).second;
+    }
+    std::vector<unsigned char> GenerateNewKey();
+};
 
 #endif
index 8949b97..e3ec47d 100644 (file)
@@ -15,8 +15,14 @@ using namespace boost;
 // Global state
 //
 
+CCriticalSection cs_setpwalletRegistered;
+set<CWallet*> setpwalletRegistered;
+
 CCriticalSection cs_main;
 
+CCriticalSection cs_mapPubKeys;
+map<uint160, vector<unsigned char> > mapPubKeys;
+
 map<uint256, CTransaction> mapTransactions;
 CCriticalSection cs_mapTransactions;
 unsigned int nTransactionsUpdated = 0;
@@ -39,25 +45,6 @@ multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
 map<uint256, CDataStream*> mapOrphanTransactions;
 multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
 
-map<uint256, CWalletTx> mapWallet;
-vector<uint256> vWalletUpdated;
-CCriticalSection cs_mapWallet;
-
-map<vector<unsigned char>, CPrivKey> mapKeys;
-map<uint160, vector<unsigned char> > mapPubKeys;
-CCriticalSection cs_mapKeys;
-CKey keyUser;
-
-map<uint256, int> mapRequestCount;
-CCriticalSection cs_mapRequestCount;
-
-map<string, string> mapAddressBook;
-CCriticalSection cs_mapAddressBook;
-
-set<int64> setKeyPool;
-CCriticalSection cs_setKeyPool;
-
-vector<unsigned char> vchDefaultKey;
 
 double dHashesPerSec;
 int64 nHPSTimerStart;
@@ -84,10 +71,95 @@ int fUseUPnP = false;
 
 //////////////////////////////////////////////////////////////////////////////
 //
+// dispatching functions
+//
+
+void RegisterWallet(CWallet* pwalletIn)
+{
+    CRITICAL_BLOCK(cs_setpwalletRegistered)
+    {
+        setpwalletRegistered.insert(pwalletIn);
+    }
+}
+
+void UnregisterWallet(CWallet* pwalletIn)
+{
+    CRITICAL_BLOCK(cs_setpwalletRegistered)
+    {
+        setpwalletRegistered.erase(pwalletIn);
+    }
+}
+
+bool static IsFromMe(CTransaction& tx)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        if (pwallet->IsFromMe(tx))
+            return true;
+    return false;
+}
+
+bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        if (pwallet->GetTransaction(hashTx,wtx))
+            return true;
+    return false;
+}
+
+void static EraseFromWallets(uint256 hash)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->EraseFromWallet(hash);
+}
+
+void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
+}
+
+void static SetBestChain(const CBlockLocator& loc)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->SetBestChain(loc);
+}
+
+void static UpdatedTransaction(const uint256& hashTx)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->UpdatedTransaction(hashTx);
+}
+
+void static PrintWallets(const CBlock& block)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->PrintWallet(block);
+}
+
+void static Inventory(const uint256& hash)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->Inventory(hash);
+}
+
+void static ResendWalletTransactions()
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->ResendWalletTransactions();
+}
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
 // mapOrphanTransactions
 //
 
-void AddOrphanTx(const CDataStream& vMsg)
+void static AddOrphanTx(const CDataStream& vMsg)
 {
     CTransaction tx;
     CDataStream(vMsg) >> tx;
@@ -99,7 +171,7 @@ void AddOrphanTx(const CDataStream& vMsg)
         mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
 }
 
-void EraseOrphanTx(uint256 hash)
+void static EraseOrphanTx(uint256 hash)
 {
     if (!mapOrphanTransactions.count(hash))
         return;
@@ -357,7 +429,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
                 nLastTime = nNow;
                 // -limitfreerelay unit is thousand-bytes-per-minute
                 // At default rate it would take over a month to fill 1GB
-                if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe())
+                if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this))
                     return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
                 if (fDebug)
                     printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
@@ -380,7 +452,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
     ///// are we sure this is ok when loading transactions or restoring block txes
     // If updated, erase old tx from wallet
     if (ptxOld)
-        EraseFromWallet(ptxOld->GetHash());
+        EraseFromWallets(ptxOld->GetHash());
 
     printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
     return true;
@@ -551,8 +623,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
     return true;
 }
 
-
-uint256 GetOrphanRoot(const CBlock* pblock)
+uint256 static GetOrphanRoot(const CBlock* pblock)
 {
     // Work back to the first block in the orphan chain
     while (mapOrphanBlocks.count(pblock->hashPrevBlock))
@@ -560,7 +631,7 @@ uint256 GetOrphanRoot(const CBlock* pblock)
     return pblock->GetHash();
 }
 
-int64 GetBlockValue(int nHeight, int64 nFees)
+int64 static GetBlockValue(int nHeight, int64 nFees)
 {
     int64 nSubsidy = 50 * COIN;
 
@@ -570,7 +641,7 @@ int64 GetBlockValue(int nHeight, int64 nFees)
     return nSubsidy + nFees;
 }
 
-unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
+unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast)
 {
     const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
     const int64 nTargetSpacing = 10 * 60;
@@ -647,7 +718,7 @@ bool IsInitialBlockDownload()
             pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
 }
 
-void InvalidChainFound(CBlockIndex* pindexNew)
+void static InvalidChainFound(CBlockIndex* pindexNew)
 {
     if (pindexNew->bnChainWork > bnBestInvalidWork)
     {
@@ -923,12 +994,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
 
     // Watch for transactions paying to me
     BOOST_FOREACH(CTransaction& tx, vtx)
-        AddToWalletIfInvolvingMe(tx, this, true);
+        SyncWithWallets(tx, this, true);
 
     return true;
 }
 
-bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
+bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
 {
     printf("REORGANIZE\n");
 
@@ -1066,10 +1137,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
     // Update best block in wallet (so we can detect restored wallets)
     if (!IsInitialBlockDownload())
     {
-        CWalletDB walletdb;
         const CBlockLocator locator(pindexNew);
-        if (!walletdb.WriteBestBlock(locator))
-            return error("SetBestChain() : WriteWalletBest failed");
+        ::SetBestChain(locator);
     }
 
     // New best block
@@ -1123,8 +1192,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
     {
         // Notify UI to display prev block's coinbase if it was ours
         static uint256 hashPrevBestCoinBase;
-        CRITICAL_BLOCK(cs_mapWallet)
-            vWalletUpdated.push_back(hashPrevBestCoinBase);
+        UpdatedTransaction(hashPrevBestCoinBase);
         hashPrevBestCoinBase = vtx[0].GetHash();
     }
 
@@ -1233,7 +1301,7 @@ bool CBlock::AcceptBlock()
     return true;
 }
 
-bool ProcessBlock(CNode* pfrom, CBlock* pblock)
+bool static ProcessBlock(CNode* pfrom, CBlock* pblock)
 {
     // Check for duplicate
     uint256 hash = pblock->GetHash();
@@ -1295,7 +1363,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
 
 
 template<typename Stream>
-bool ScanMessageStart(Stream& s)
+bool static ScanMessageStart(Stream& s)
 {
     // Scan ahead to the next pchMessageStart, which should normally be immediately
     // at the file pointer.  Leaves file pointer at end of pchMessageStart.
@@ -1510,7 +1578,7 @@ void PrintBlockTree()
             for (int i = 0; i < nCol; i++)
                 printf("| ");
             printf("|\n");
-        }
+       }
         nPrevCol = nCol;
 
         // print columns
@@ -1528,16 +1596,7 @@ void PrintBlockTree()
             DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
             block.vtx.size());
 
-        CRITICAL_BLOCK(cs_mapWallet)
-        {
-            if (mapWallet.count(block.vtx[0].GetHash()))
-            {
-                CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
-                printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
-            }
-        }
-        printf("\n");
-
+        PrintWallets(block);
 
         // put the main timechain first
         vector<CBlockIndex*>& vNext = mapNext[pindex];
@@ -1677,7 +1736,7 @@ bool CAlert::ProcessAlert()
 //
 
 
-bool AlreadyHave(CTxDB& txdb, const CInv& inv)
+bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
 {
     switch (inv.type)
     {
@@ -1697,7 +1756,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
 char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
 
 
-bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
+bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 {
     static map<unsigned int, vector<unsigned char> > mapReuseKey;
     RandAddSeedPerfmon();
@@ -1894,12 +1953,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                 pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
 
             // Track requests for our stuff
-            CRITICAL_BLOCK(cs_mapRequestCount)
-            {
-                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
-                if (mi != mapRequestCount.end())
-                    (*mi).second++;
-            }
+            Inventory(inv.hash);
         }
     }
 
@@ -1952,12 +2006,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             }
 
             // Track requests for our stuff
-            CRITICAL_BLOCK(cs_mapRequestCount)
-            {
-                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
-                if (mi != mapRequestCount.end())
-                    (*mi).second++;
-            }
+            Inventory(inv.hash);
         }
     }
 
@@ -2045,7 +2094,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         bool fMissingInputs = false;
         if (tx.AcceptToMemoryPool(true, &fMissingInputs))
         {
-            AddToWalletIfInvolvingMe(tx, NULL, true);
+            SyncWithWallets(tx, NULL, true);
             RelayMessage(inv, vMsg);
             mapAlreadyAskedFor.erase(inv);
             vWorkQueue.push_back(inv.hash);
@@ -2066,7 +2115,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                     if (tx.AcceptToMemoryPool(true))
                     {
                         printf("   accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
-                        AddToWalletIfInvolvingMe(tx, NULL, true);
+                        SyncWithWallets(tx, NULL, true);
                         RelayMessage(inv, vMsg);
                         mapAlreadyAskedFor.erase(inv);
                         vWorkQueue.push_back(inv.hash);
@@ -2143,7 +2192,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 
         // Keep giving the same key to the same ip until they use it
         if (!mapReuseKey.count(pfrom->addr.ip))
-            mapReuseKey[pfrom->addr.ip] = GetKeyFromKeyPool();
+            mapReuseKey[pfrom->addr.ip] = pwalletMain->GetKeyFromKeyPool();
 
         // Send back approval of order and pubkey to use
         CScript scriptPubKey;
@@ -2152,37 +2201,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     }
 
 
-    else if (strCommand == "submitorder")
-    {
-        uint256 hashReply;
-        vRecv >> hashReply;
-
-        if (!GetBoolArg("-allowreceivebyip"))
-        {
-            pfrom->PushMessage("reply", hashReply, (int)2);
-            return true;
-        }
-
-        CWalletTx wtxNew;
-        vRecv >> wtxNew;
-        wtxNew.fFromMe = false;
-
-        // Broadcast
-        if (!wtxNew.AcceptWalletTransaction())
-        {
-            pfrom->PushMessage("reply", hashReply, (int)1);
-            return error("submitorder AcceptWalletTransaction() failed, returning error 1");
-        }
-        wtxNew.fTimeReceivedIsTxTime = true;
-        AddToWallet(wtxNew);
-        wtxNew.RelayWalletTransaction();
-        mapReuseKey.erase(pfrom->addr.ip);
-
-        // Send back confirmation
-        pfrom->PushMessage("reply", hashReply, (int)0);
-    }
-
-
     else if (strCommand == "reply")
     {
         uint256 hashReply;
@@ -2239,7 +2257,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     return true;
 }
 
-
 bool ProcessMessages(CNode* pfrom)
 {
     CDataStream& vRecv = pfrom->vRecv;
@@ -2359,8 +2376,6 @@ bool ProcessMessages(CNode* pfrom)
 }
 
 
-
-
 bool SendMessages(CNode* pto, bool fSendTrickle)
 {
     CRITICAL_BLOCK(cs_main)
@@ -2483,16 +2498,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
                     // always trickle our own transactions
                     if (!fTrickleWait)
                     {
-                        TRY_CRITICAL_BLOCK(cs_mapWallet)
-                        {
-                            map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash);
-                            if (mi != mapWallet.end())
-                            {
-                                CWalletTx& wtx = (*mi).second;
-                                if (wtx.fFromMe)
-                                    fTrickleWait = true;
-                            }
-                        }
+                        CWalletTx wtx;
+                        if (GetTransaction(inv.hash, wtx))
+                            if (wtx.fFromMe)
+                                fTrickleWait = true;
                     }
 
                     if (fTrickleWait)
@@ -2565,7 +2574,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
 // BitcoinMiner
 //
 
-int FormatHashBlocks(void* pbuffer, unsigned int len)
+int static FormatHashBlocks(void* pbuffer, unsigned int len)
 {
     unsigned char* pdata = (unsigned char*)pbuffer;
     unsigned int blocks = 1 + ((len + 8) / 64);
@@ -2598,7 +2607,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)
 // between calls, but periodically or if nNonce is 0xffff0000 or above,
 // the block is rebuilt and nNonce starts over at zero.
 //
-unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
+unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
 {
     unsigned int& nNonce = *(unsigned int*)(pdata + 12);
     for (;;)
@@ -2855,7 +2864,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
 }
 
 
-bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
+bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
 {
     uint256 hash = pblock->GetHash();
     uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
@@ -2880,8 +2889,8 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
         reservekey.KeepKey();
 
         // Track how many getdata requests this block gets
-        CRITICAL_BLOCK(cs_mapRequestCount)
-            mapRequestCount[pblock->GetHash()] = 0;
+        CRITICAL_BLOCK(wallet.cs_mapRequestCount)
+            wallet.mapRequestCount[pblock->GetHash()] = 0;
 
         // Process this block the same as if we had received it from another node
         if (!ProcessBlock(NULL, pblock))
@@ -2892,13 +2901,15 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
     return true;
 }
 
-void BitcoinMiner()
+void static ThreadBitcoinMiner(void* parg);
+
+void static BitcoinMiner(CWallet *pwallet)
 {
     printf("BitcoinMiner started\n");
     SetThreadPriority(THREAD_PRIORITY_LOWEST);
 
     // Each thread has its own key and counter
-    CReserveKey reservekey;
+    CReserveKey reservekey(pwallet);
     unsigned int nExtraNonce = 0;
     int64 nPrevTime = 0;
 
@@ -2974,7 +2985,7 @@ void BitcoinMiner()
                     assert(hash == pblock->GetHash());
 
                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
-                    CheckWork(pblock.get(), reservekey);
+                    CheckWork(pblock.get(), *pwalletMain, reservekey);
                     SetThreadPriority(THREAD_PRIORITY_LOWEST);
                     break;
                 }
@@ -3035,12 +3046,13 @@ void BitcoinMiner()
     }
 }
 
-void ThreadBitcoinMiner(void* parg)
+void static ThreadBitcoinMiner(void* parg)
 {
+    CWallet* pwallet = (CWallet*)parg;
     try
     {
         vnThreadsRunning[3]++;
-        BitcoinMiner();
+        BitcoinMiner(pwallet);
         vnThreadsRunning[3]--;
     }
     catch (std::exception& e) {
@@ -3058,12 +3070,12 @@ void ThreadBitcoinMiner(void* parg)
 }
 
 
-void GenerateBitcoins(bool fGenerate)
+void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
 {
     if (fGenerateBitcoins != fGenerate)
     {
         fGenerateBitcoins = fGenerate;
-        CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
+        WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
         MainFrameRepaint();
     }
     if (fGenerateBitcoins)
@@ -3078,7 +3090,7 @@ void GenerateBitcoins(bool fGenerate)
         printf("Starting %d BitcoinMiner threads\n", nAddThreads);
         for (int i = 0; i < nAddThreads; i++)
         {
-            if (!CreateThread(ThreadBitcoinMiner, NULL))
+            if (!CreateThread(ThreadBitcoinMiner, pwallet))
                 printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
             Sleep(10);
         }
index 2ebb8b8..3b35387 100644 (file)
@@ -8,21 +8,17 @@
 #include "net.h"
 #include "key.h"
 #include "script.h"
+#include "db.h"
 
 #include <list>
 
-class COutPoint;
-class CInPoint;
-class CDiskTxPos;
-class CCoinBase;
-class CTxIn;
-class CTxOut;
-class CTransaction;
 class CBlock;
 class CBlockIndex;
 class CWalletTx;
 class CWallet;
 class CKeyItem;
+class CReserveKey;
+class CWalletDB;
 
 class CMessageHeader;
 class CAddress;
@@ -62,15 +58,12 @@ extern CBigNum bnBestChainWork;
 extern CBigNum bnBestInvalidWork;
 extern uint256 hashBestChain;
 extern CBlockIndex* pindexBest;
-extern std::set<int64> setKeyPool;
-extern CCriticalSection cs_setKeyPool;
 extern unsigned int nTransactionsUpdated;
 extern double dHashesPerSec;
 extern int64 nHPSTimerStart;
 extern int64 nTimeBestReceived;
-extern std::map<std::string, std::string> mapAddressBook;
-extern CCriticalSection cs_mapAddressBook;
-
+extern CCriticalSection cs_setpwalletRegistered;
+extern std::set<CWallet*> setpwalletRegistered;
 
 // Settings
 extern int fGenerateBitcoins;
@@ -90,21 +83,20 @@ class CReserveKey;
 class CTxDB;
 class CTxIndex;
 
+void RegisterWallet(CWallet* pwalletIn);
+void UnregisterWallet(CWallet* pwalletIn);
 bool CheckDiskSpace(uint64 nAdditionalBytes=0);
 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
 FILE* AppendBlockFile(unsigned int& nFileRet);
 bool LoadBlockIndex(bool fAllowNew=true);
 void PrintBlockTree();
 bool ProcessMessages(CNode* pfrom);
-bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv);
 bool SendMessages(CNode* pto, bool fSendTrickle);
-void GenerateBitcoins(bool fGenerate);
-void ThreadBitcoinMiner(void* parg);
+void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
 CBlock* CreateNewBlock(CReserveKey& reservekey);
 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
-bool CheckWork(CBlock* pblock, CReserveKey& reservekey);
-void BitcoinMiner();
+bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
 bool CheckProofOfWork(uint256 hash, unsigned int nBits);
 bool IsInitialBlockDownload();
 std::string GetWarnings(std::string strFor);
@@ -120,6 +112,23 @@ std::string GetWarnings(std::string strFor);
 
 
 
+bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
+
+template<typename T>
+bool WriteSetting(const std::string& strKey, const T& value)
+{
+    bool fOk = false;
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+    {
+        std::string strWalletFile;
+        if (!GetWalletFile(pwallet, strWalletFile))
+            continue;
+        fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
+    }
+    return fOk;
+}
+
+
 class CDiskTxPos
 {
 public:
@@ -302,9 +311,6 @@ public:
     {
         printf("%s\n", ToString().c_str());
     }
-
-    bool IsMine() const;
-    int64 GetDebit() const;
 };
 
 
@@ -353,36 +359,6 @@ public:
         return SerializeHash(*this);
     }
 
-    bool IsMine() const
-    {
-        return ::IsMine(scriptPubKey);
-    }
-
-    int64 GetCredit() const
-    {
-        if (!MoneyRange(nValue))
-            throw std::runtime_error("CTxOut::GetCredit() : value out of range");
-        return (IsMine() ? nValue : 0);
-    }
-
-    bool IsChange() const
-    {
-        // On a debit transaction, a txout that's mine but isn't in the address book is change
-        std::vector<unsigned char> vchPubKey;
-        if (ExtractPubKey(scriptPubKey, true, vchPubKey))
-            CRITICAL_BLOCK(cs_mapAddressBook)
-                if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
-                    return true;
-        return false;
-    }
-
-    int64 GetChange() const
-    {
-        if (!MoneyRange(nValue))
-            throw std::runtime_error("CTxOut::GetChange() : value out of range");
-        return (IsChange() ? nValue : 0);
-    }
-
     friend bool operator==(const CTxOut& a, const CTxOut& b)
     {
         return (a.nValue       == b.nValue &&
@@ -527,57 +503,6 @@ public:
         return true;
     }
 
-    bool IsMine() const
-    {
-        BOOST_FOREACH(const CTxOut& txout, vout)
-            if (txout.IsMine())
-                return true;
-        return false;
-    }
-
-    bool IsFromMe() const
-    {
-        return (GetDebit() > 0);
-    }
-
-    int64 GetDebit() const
-    {
-        int64 nDebit = 0;
-        BOOST_FOREACH(const CTxIn& txin, vin)
-        {
-            nDebit += txin.GetDebit();
-            if (!MoneyRange(nDebit))
-                throw std::runtime_error("CTransaction::GetDebit() : value out of range");
-        }
-        return nDebit;
-    }
-
-    int64 GetCredit() const
-    {
-        int64 nCredit = 0;
-        BOOST_FOREACH(const CTxOut& txout, vout)
-        {
-            nCredit += txout.GetCredit();
-            if (!MoneyRange(nCredit))
-                throw std::runtime_error("CTransaction::GetCredit() : value out of range");
-        }
-        return nCredit;
-    }
-
-    int64 GetChange() const
-    {
-        if (IsCoinBase())
-            return 0;
-        int64 nChange = 0;
-        BOOST_FOREACH(const CTxOut& txout, vout)
-        {
-            nChange += txout.GetChange();
-            if (!MoneyRange(nChange))
-                throw std::runtime_error("CTransaction::GetChange() : value out of range");
-        }
-        return nChange;
-    }
-
     int64 GetValueOut() const
     {
         int64 nValueOut = 0;
@@ -1639,9 +1564,9 @@ public:
 
 
 
+
 extern std::map<uint256, CTransaction> mapTransactions;
-extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
 extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
-extern CCriticalSection cs_mapKeys;
+extern CCriticalSection cs_mapPubKeys;
 
 #endif
index 8b439ef..4b13726 100644 (file)
@@ -1117,7 +1117,7 @@ void MapPort(bool fMapPort)
     if (fUseUPnP != fMapPort)
     {
         fUseUPnP = fMapPort;
-        CWalletDB().WriteSetting("fUseUPnP", fUseUPnP);
+        WriteSetting("fUseUPnP", fUseUPnP);
     }
     if (fUseUPnP && vnThreadsRunning[5] < 1)
     {
@@ -1698,7 +1698,7 @@ void StartNode(void* parg)
         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
 
     // Generate coins in the background
-    GenerateBitcoins(fGenerateBitcoins);
+    GenerateBitcoins(fGenerateBitcoins, pwalletMain);
 }
 
 bool StopNode()
index ad1abe3..5b395f9 100644 (file)
@@ -264,14 +264,14 @@ Value setgenerate(const Array& params, bool fHelp)
     {
         int nGenProcLimit = params[1].get_int();
         fLimitProcessors = (nGenProcLimit != -1);
-        CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
+        WriteSetting("fLimitProcessors", fLimitProcessors);
         if (nGenProcLimit != -1)
-            CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
+            WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
         if (nGenProcLimit == 0)
             fGenerate = false;
     }
 
-    GenerateBitcoins(fGenerate);
+    GenerateBitcoins(fGenerate, pwalletMain);
     return Value::null;
 }
 
@@ -298,7 +298,7 @@ Value getinfo(const Array& params, bool fHelp)
 
     Object obj;
     obj.push_back(Pair("version",       (int)VERSION));
-    obj.push_back(Pair("balance",       ValueFromAmount(GetBalance())));
+    obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
     obj.push_back(Pair("blocks",        (int)nBestHeight));
     obj.push_back(Pair("connections",   (int)vNodes.size()));
     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
@@ -307,7 +307,7 @@ Value getinfo(const Array& params, bool fHelp)
     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
     obj.push_back(Pair("testnet",       fTestNet));
-    obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
+    obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
     return obj;
@@ -329,9 +329,9 @@ Value getnewaddress(const Array& params, bool fHelp)
         strAccount = AccountFromValue(params[0]);
 
     // Generate a new key that is added to wallet
-    string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+    string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
 
-    SetAddressBookName(strAddress, strAccount);
+    pwalletMain->SetAddressBookName(strAddress, strAccount);
     return strAddress;
 }
 
@@ -341,7 +341,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
 {
     string strAddress;
 
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
     walletdb.TxnBegin();
 
     CAccount account;
@@ -352,8 +352,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
     {
         CScript scriptPubKey;
         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
-             it != mapWallet.end() && !account.vchPubKey.empty();
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
+             it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
              ++it)
         {
             const CWalletTx& wtx = (*it).second;
@@ -366,9 +366,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
     // Generate a new key
     if (account.vchPubKey.empty() || bForceNew)
     {
-        account.vchPubKey = GetKeyFromKeyPool();
+        account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
         string strAddress = PubKeyToAddress(account.vchPubKey);
-        SetAddressBookName(strAddress, strAccount);
+        pwalletMain->SetAddressBookName(strAddress, strAccount);
         walletdb.WriteAccount(strAccount, account);
     }
 
@@ -391,7 +391,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
     Value ret;
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         ret = GetAccountAddress(strAccount);
     }
@@ -421,18 +421,18 @@ Value setaccount(const Array& params, bool fHelp)
 
     // Detect when changing the account of an address that is the 'unused current key' of another account:
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        if (mapAddressBook.count(strAddress))
+        if (pwalletMain->mapAddressBook.count(strAddress))
         {
-            string strOldAccount = mapAddressBook[strAddress];
+            string strOldAccount = pwalletMain->mapAddressBook[strAddress];
             if (strAddress == GetAccountAddress(strOldAccount))
                 GetAccountAddress(strOldAccount, true);
         }
     }
 
-    SetAddressBookName(strAddress, strAccount);
+    pwalletMain->SetAddressBookName(strAddress, strAccount);
     return Value::null;
 }
 
@@ -447,10 +447,10 @@ Value getaccount(const Array& params, bool fHelp)
     string strAddress = params[0].get_str();
 
     string strAccount;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        map<string, string>::iterator mi = mapAddressBook.find(strAddress);
-        if (mi != mapAddressBook.end() && !(*mi).second.empty())
+        map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+        if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
             strAccount = (*mi).second;
     }
     return strAccount;
@@ -468,9 +468,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
 
     // Find all addresses that have the given account
     Array ret;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strName = item.second;
@@ -523,7 +523,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
 
     CRITICAL_BLOCK(cs_main)
     {
-        string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
+        string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
         if (strError != "")
             throw JSONRPCError(-4, strError);
     }
@@ -544,7 +544,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
     CScript scriptPubKey;
     if (!scriptPubKey.SetBitcoinAddress(strAddress))
         throw JSONRPCError(-5, "Invalid bitcoin address");
-    if (!IsMine(scriptPubKey))
+    if (!IsMine(*pwalletMain,scriptPubKey))
         return (double)0.0;
 
     // Minimum confirmations
@@ -554,9 +554,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
 
     // Tally
     int64 nAmount = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -575,9 +575,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
 
 void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
 {
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strName = item.second;
@@ -586,7 +586,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
                 // We're only counting our own valid bitcoin addresses and not ip addresses
                 CScript scriptPubKey;
                 if (scriptPubKey.SetBitcoinAddress(strAddress))
-                    if (IsMine(scriptPubKey))
+                    if (IsMine(*pwalletMain,scriptPubKey))
                         setPubKey.insert(scriptPubKey);
             }
         }
@@ -613,9 +613,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
 
     // Tally
     int64 nAmount = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -635,10 +635,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
 {
     int64 nBalance = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Tally wallet transactions
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (!wtx.IsFinal())
@@ -661,7 +661,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
 
 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
 {
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
     return GetAccountBalance(walletdb, strAccount, nMinDepth);
 }
 
@@ -675,7 +675,7 @@ Value getbalance(const Array& params, bool fHelp)
             "If [account] is specified, returns the balance in the account.");
 
     if (params.size() == 0)
-        return  ValueFromAmount(GetBalance());
+        return  ValueFromAmount(pwalletMain->GetBalance());
 
     int nMinDepth = 1;
     if (params.size() > 1)
@@ -686,7 +686,7 @@ Value getbalance(const Array& params, bool fHelp)
         // (GetBalance() sums up all unspent TxOuts)
         // getbalance and getbalance '*' should always return the same number.
         int64 nBalance = 0;
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (!wtx.IsFinal())
@@ -734,9 +734,9 @@ Value movecmd(const Array& params, bool fHelp)
     if (params.size() > 4)
         strComment = params[4].get_str();
 
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        CWalletDB walletdb;
+        CWalletDB walletdb(pwalletMain->strWalletFile);
         walletdb.TxnBegin();
 
         int64 nNow = GetAdjustedTime();
@@ -787,7 +787,7 @@ Value sendfrom(const Array& params, bool fHelp)
         wtx.mapValue["to"]      = params[5].get_str();
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Check funds
         int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -795,7 +795,7 @@ Value sendfrom(const Array& params, bool fHelp)
             throw JSONRPCError(-6, "Account has insufficient funds");
 
         // Send
-        string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
+        string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
         if (strError != "")
             throw JSONRPCError(-4, strError);
     }
@@ -844,7 +844,7 @@ Value sendmany(const Array& params, bool fHelp)
     }
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Check funds
         int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -852,16 +852,16 @@ Value sendmany(const Array& params, bool fHelp)
             throw JSONRPCError(-6, "Account has insufficient funds");
 
         // Send
-        CReserveKey keyChange;
+        CReserveKey keyChange(pwalletMain);
         int64 nFeeRequired = 0;
-        bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
+        bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
         if (!fCreated)
         {
-            if (totalAmount + nFeeRequired > GetBalance())
+            if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
                 throw JSONRPCError(-6, "Insufficient funds");
             throw JSONRPCError(-4, "Transaction creation failed");
         }
-        if (!CommitTransaction(wtx, keyChange))
+        if (!pwalletMain->CommitTransaction(wtx, keyChange))
             throw JSONRPCError(-4, "Transaction commit failed");
     }
 
@@ -894,9 +894,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
 
     // Tally
     map<uint160, tallyitem> mapTally;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -923,9 +923,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
     // Reply
     Array ret;
     map<string, tallyitem> mapAccountTally;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strAccount = item.second;
@@ -1061,13 +1061,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
 
     // Received
     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
-        CRITICAL_BLOCK(cs_mapAddressBook)
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
             BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
             {
                 string account;
-                if (mapAddressBook.count(r.first))
-                    account = mapAddressBook[r.first];
+                if (pwalletMain->mapAddressBook.count(r.first))
+                    account = pwalletMain->mapAddressBook[r.first];
                 if (fAllAccounts || (account == strAccount))
                 {
                     Object entry;
@@ -1119,16 +1119,16 @@ Value listtransactions(const Array& params, bool fHelp)
         nFrom = params[2].get_int();
 
     Array ret;
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
 
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
         typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
         typedef multimap<int64, TxPair > TxItems;
         TxItems txByTime;
 
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             CWalletTx* wtx = &((*it).second);
             txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
@@ -1180,16 +1180,16 @@ Value listaccounts(const Array& params, bool fHelp)
         nMinDepth = params[0].get_int();
 
     map<string, int64> mapAccountBalances;
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) {
+        BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
             uint160 hash160;
             if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
                 mapAccountBalances[entry.second] = 0;
         }
 
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             int64 nGeneratedImmature, nGeneratedMature, nFee;
@@ -1204,8 +1204,8 @@ Value listaccounts(const Array& params, bool fHelp)
             {
                 mapAccountBalances[""] += nGeneratedMature;
                 BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
-                    if (mapAddressBook.count(r.first))
-                        mapAccountBalances[mapAddressBook[r.first]] += r.second;
+                    if (pwalletMain->mapAddressBook.count(r.first))
+                        mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
                     else
                         mapAccountBalances[""] += r.second;
             }
@@ -1213,7 +1213,7 @@ Value listaccounts(const Array& params, bool fHelp)
     }
 
     list<CAccountingEntry> acentries;
-    CWalletDB().ListAccountCreditDebit("*", acentries);
+    CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
 
@@ -1235,11 +1235,11 @@ Value gettransaction(const Array& params, bool fHelp)
     hash.SetHex(params[0].get_str());
 
     Object entry;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        if (!mapWallet.count(hash))
+        if (!pwalletMain->mapWallet.count(hash))
             throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
-        const CWalletTx& wtx = mapWallet[hash];
+        const CWalletTx& wtx = pwalletMain->mapWallet[hash];
 
         int64 nCredit = wtx.GetCredit();
         int64 nDebit = wtx.GetDebit();
@@ -1250,10 +1250,10 @@ Value gettransaction(const Array& params, bool fHelp)
         if (wtx.IsFromMe())
             entry.push_back(Pair("fee", ValueFromAmount(nFee)));
 
-        WalletTxToJSON(mapWallet[hash], entry);
+        WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
 
         Array details;
-        ListTransactions(mapWallet[hash], "*", 0, false, details);
+        ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
         entry.push_back(Pair("details", details));
     }
 
@@ -1269,7 +1269,7 @@ Value backupwallet(const Array& params, bool fHelp)
             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
 
     string strDest = params[0].get_str();
-    BackupWallet(strDest);
+    BackupWallet(*pwalletMain, strDest);
 
     return Value::null;
 }
@@ -1295,10 +1295,10 @@ Value validateaddress(const Array& params, bool fHelp)
         string currentAddress = Hash160ToAddress(hash160);
         ret.push_back(Pair("address", currentAddress));
         ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
-        CRITICAL_BLOCK(cs_mapAddressBook)
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
-            if (mapAddressBook.count(currentAddress))
-                ret.push_back(Pair("account", mapAddressBook[currentAddress]));
+            if (pwalletMain->mapAddressBook.count(currentAddress))
+                ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
         }
     }
     return ret;
@@ -1325,7 +1325,7 @@ Value getwork(const Array& params, bool fHelp)
 
     static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
     static vector<CBlock*> vNewBlock;
-    static CReserveKey reservekey;
+    static CReserveKey reservekey(pwalletMain);
 
     if (params.size() == 0)
     {
@@ -1406,7 +1406,7 @@ Value getwork(const Array& params, bool fHelp)
         pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
 
-        return CheckWork(pblock, reservekey);
+        return CheckWork(pblock, *pwalletMain, reservekey);
     }
 }
 
index 97334ca..e1b5ae8 100644 (file)
@@ -1021,7 +1021,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
 }
 
 
-bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
 {
     scriptSigRet.clear();
 
@@ -1030,7 +1030,7 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
         return false;
 
     // Compile solution
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(keystore.cs_mapKeys)
     {
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
@@ -1038,12 +1038,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
             {
                 // Sign
                 const valtype& vchPubKey = item.second;
-                if (!mapKeys.count(vchPubKey))
+                if (!keystore.HaveKey(vchPubKey))
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
                     scriptSigRet << vchSig;
@@ -1056,12 +1056,12 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
                 if (mi == mapPubKeys.end())
                     return false;
                 const vector<unsigned char>& vchPubKey = (*mi).second;
-                if (!mapKeys.count(vchPubKey))
+                if (!keystore.HaveKey(vchPubKey))
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!CKey::Sign(keystore.GetPrivKey(vchPubKey), hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
                     scriptSigRet << vchSig << vchPubKey;
@@ -1085,14 +1085,14 @@ bool IsStandard(const CScript& scriptPubKey)
 }
 
 
-bool IsMine(const CScript& scriptPubKey)
+bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
 {
     CScript scriptSig;
-    return Solver(scriptPubKey, 0, 0, scriptSig);
+    return Solver(keystore, scriptPubKey, 0, 0, scriptSig);
 }
 
 
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
+bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vector<unsigned char>& vchPubKeyRet)
 {
     vchPubKeyRet.clear();
 
@@ -1100,7 +1100,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
     if (!Solver(scriptPubKey, vSolution))
         return false;
 
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(cs_mapPubKeys)
     {
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
@@ -1116,7 +1116,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
                     continue;
                 vchPubKey = (*mi).second;
             }
-            if (!fMineOnly || mapKeys.count(vchPubKey))
+            if (keystore == NULL || keystore->HaveKey(vchPubKey))
             {
                 vchPubKeyRet = vchPubKey;
                 return true;
@@ -1160,7 +1160,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
 }
 
 
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
 {
     assert(nIn < txTo.vin.size());
     CTxIn& txin = txTo.vin[nIn];
@@ -1171,7 +1171,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
     // The checksig op will also drop the signatures from its hash.
     uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
 
-    if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
+    if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig))
         return false;
 
     txin.scriptSig = scriptPrereq + txin.scriptSig;
@@ -1199,10 +1199,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
     if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
         return false;
 
-    // Anytime a signature is successfully verified, it's proof the outpoint is spent,
-    // so lets update the wallet spent flag if it doesn't know due to wallet.dat being
-    // restored from backup or the user making copies of wallet.dat.
-    WalletUpdateSpent(txin.prevout);
-
     return true;
 }
index efafec4..ae9fdff 100644 (file)
@@ -708,12 +708,11 @@ public:
 
 
 
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
 bool IsStandard(const CScript& scriptPubKey);
-bool IsMine(const CScript& scriptPubKey);
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet);
+bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
+bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet);
 bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
+bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
 bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
 
 #endif
index 72e8fe2..a49741f 100644 (file)
@@ -240,7 +240,7 @@ void SetDefaultReceivingAddress(const string& strAddress)
             return;
         if (!mapPubKeys.count(hash160))
             return;
-        CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
+        CWalletDB(pwalletMain->strWalletFile).WriteDefaultKey(mapPubKeys[hash160]);
         pframeMain->m_textCtrlAddress->SetValue(strAddress);
     }
 }
@@ -290,7 +290,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     dResize = 1.22;
     SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
 #endif
-    m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+    m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
     m_listCtrl->SetFocus();
     ptaskbaricon = new CMyTaskBarIcon();
 #ifdef __WXMAC_OSX__
@@ -330,7 +330,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
 
     // Fill your address text box
     vector<unsigned char> vchPubKey;
-    if (CWalletDB("r").ReadDefaultKey(vchPubKey))
+    if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
         m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
 
     // Fill listctrl with wallet transactions
@@ -625,7 +625,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             {
                 int64 nUnmatured = 0;
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    nUnmatured += txout.GetCredit();
+                    nUnmatured += pwalletMain->GetCredit(txout);
                 if (wtx.IsInMainChain())
                 {
                     strDescription = strprintf(_("Generated (%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -661,19 +661,19 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 return false;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
             {
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                 {
                     vector<unsigned char> vchPubKey;
-                    if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                    if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                     {
-                        CRITICAL_BLOCK(cs_mapAddressBook)
+                        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
                         {
                             //strDescription += _("Received payment to ");
                             //strDescription += _("Received with address ");
                             strDescription += _("Received with: ");
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            map<string, string>::iterator mi = mapAddressBook.find(strAddress);
-                            if (mi != mapAddressBook.end() && !(*mi).second.empty())
+                            map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+                            if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
                             {
                                 string strLabel = (*mi).second;
                                 strDescription += strAddress.substr(0,12) + "... ";
@@ -703,11 +703,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
     {
         bool fAllFromMe = true;
         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-            fAllFromMe = fAllFromMe && txin.IsMine();
+            fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
         bool fAllToMe = true;
         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-            fAllToMe = fAllToMe && txout.IsMine();
+            fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
         if (fAllFromMe && fAllToMe)
         {
@@ -733,7 +733,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
             {
                 const CTxOut& txout = wtx.vout[nOut];
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                     continue;
 
                 string strAddress;
@@ -751,9 +751,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 }
 
                 string strDescription = _("To: ");
-                CRITICAL_BLOCK(cs_mapAddressBook)
-                    if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                        strDescription += mapAddressBook[strAddress] + " ";
+                CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+                    if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                        strDescription += pwalletMain->mapAddressBook[strAddress] + " ";
                 strDescription += strAddress;
                 if (!mapValue["message"].empty())
                 {
@@ -792,9 +792,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             //
             bool fAllMine = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllMine = fAllMine && txout.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txout);
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllMine = fAllMine && txin.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txin);
 
             InsertLine(fNew, nIndex, hash, strSort, colour,
                        strStatus,
@@ -821,16 +821,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         // Collect list of wallet transactions and sort newest first
         bool fEntered = false;
         vector<pair<unsigned int, uint256> > vSorted;
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             printf("RefreshListCtrl starting\n");
             fEntered = true;
             fRefreshListCtrl = false;
-            vWalletUpdated.clear();
+            pwalletMain->vWalletUpdated.clear();
 
             // Do the newest transactions first
-            vSorted.reserve(mapWallet.size());
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            vSorted.reserve(pwalletMain->mapWallet.size());
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 const CWalletTx& wtx = (*it).second;
                 unsigned int nTime = UINT_MAX - wtx.GetTxTime();
@@ -849,12 +849,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
             if (fShutdown)
                 return;
             bool fEntered = false;
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 fEntered = true;
                 uint256& hash = vSorted[i++].second;
-                map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                if (mi != mapWallet.end())
+                map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                if (mi != pwalletMain->mapWallet.end())
                     InsertTransaction((*mi).second, true);
             }
             if (!fEntered || i == 100 || i % 500 == 0)
@@ -872,10 +872,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         static int64 nLastTime;
         if (GetTime() > nLastTime + 30)
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 nLastTime = GetTime();
-                for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+                for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
                 {
                     CWalletTx& wtx = (*it).second;
                     if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime())
@@ -896,7 +896,7 @@ void CMainFrame::RefreshStatusColumn()
     if (nTop == nLastTop && pindexLastBest == pindexBest)
         return;
 
-    TRY_CRITICAL_BLOCK(cs_mapWallet)
+    TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         int nStart = nTop;
         int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
@@ -916,8 +916,8 @@ void CMainFrame::RefreshStatusColumn()
         for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
         {
             uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
-            map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-            if (mi == mapWallet.end())
+            map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+            if (mi == pwalletMain->mapWallet.end())
             {
                 printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n");
                 continue;
@@ -1014,41 +1014,41 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
         nLastRepaintTime = GetTimeMillis();
 
         // Update listctrl contents
-        if (!vWalletUpdated.empty())
+        if (!pwalletMain->vWalletUpdated.empty())
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 string strTop;
                 if (m_listCtrl->GetItemCount())
                     strTop = (string)m_listCtrl->GetItemText(0);
-                BOOST_FOREACH(uint256 hash, vWalletUpdated)
+                BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated)
                 {
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                    if (mi != pwalletMain->mapWallet.end())
                         InsertTransaction((*mi).second, false);
                 }
-                vWalletUpdated.clear();
+                pwalletMain->vWalletUpdated.clear();
                 if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
                     m_listCtrl->ScrollList(0, INT_MIN/2);
             }
         }
 
         // Balance total
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             fPaintedBalance = true;
-            m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+            m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
 
             // Count hidden and multi-line transactions
             nTransactionCount = 0;
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 CWalletTx& wtx = (*it).second;
                 nTransactionCount += wtx.nLinesDisplayed;
             }
         }
     }
-    if (!vWalletUpdated.empty() || !fPaintedBalance)
+    if (!pwalletMain->vWalletUpdated.empty() || !fPaintedBalance)
         nNeedRepaint++;
 
     // Update status column of visible items only
@@ -1074,7 +1074,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     m_statusBar->SetStatusText(strStatus, 2);
 
     // Update receiving address
-    string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
+    string strDefaultAddress = PubKeyToAddress(pwalletMain->vchDefaultKey);
     if (m_textCtrlAddress->GetValue() != strDefaultAddress)
         m_textCtrlAddress->SetValue(strDefaultAddress);
 }
@@ -1183,10 +1183,10 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
     string strName = dialog.GetValue();
 
     // Generate new key
-    string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+    string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
 
     // Save
-    SetAddressBookName(strAddress, strName);
+    pwalletMain->SetAddressBookName(strAddress, strName);
     SetDefaultReceivingAddress(strAddress);
 }
 
@@ -1204,10 +1204,10 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
 {
     uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
     CWalletTx wtx;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-        if (mi == mapWallet.end())
+        map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+        if (mi == pwalletMain->mapWallet.end())
         {
             printf("CMainFrame::OnListItemActivated() : tx not found in mapWallet\n");
             return;
@@ -1235,7 +1235,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
 #ifdef __WXMSW__
     SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strHTML;
         strHTML.reserve(4000);
@@ -1285,19 +1285,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Credit
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                     {
                         vector<unsigned char> vchPubKey;
-                        if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                        if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                         {
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            if (mapAddressBook.count(strAddress))
+                            if (pwalletMain->mapAddressBook.count(strAddress))
                             {
                                 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
                                 strHTML += _("<b>To:</b> ");
                                 strHTML += HtmlEscape(strAddress);
-                                if (!mapAddressBook[strAddress].empty())
-                                    strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
+                                if (!pwalletMain->mapAddressBook[strAddress].empty())
+                                    strHTML += _(" (yours, label: ") + pwalletMain->mapAddressBook[strAddress] + ")";
                                 else
                                     strHTML += _(" (yours)");
                                 strHTML += "<br>";
@@ -1319,8 +1319,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             // Online transaction
             strAddress = wtx.mapValue["to"];
             strHTML += _("<b>To:</b> ");
-            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                strHTML += mapAddressBook[strAddress] + " ";
+            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
             strHTML += HtmlEscape(strAddress) + "<br>";
         }
 
@@ -1335,7 +1335,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             //
             int64 nUnmatured = 0;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                nUnmatured += txout.GetCredit();
+                nUnmatured += pwalletMain->GetCredit(txout);
             strHTML += _("<b>Credit:</b> ");
             if (wtx.IsInMainChain())
                 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -1354,11 +1354,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             bool fAllFromMe = true;
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllFromMe = fAllFromMe && txin.IsMine();
+                fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
             bool fAllToMe = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllToMe = fAllToMe && txout.IsMine();
+                fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
             if (fAllFromMe)
             {
@@ -1367,7 +1367,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 //
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                         continue;
 
                     if (wtx.mapValue["to"].empty())
@@ -1378,8 +1378,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                         {
                             string strAddress = Hash160ToAddress(hash160);
                             strHTML += _("<b>To:</b> ");
-                            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                                strHTML += mapAddressBook[strAddress] + " ";
+                            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
                             strHTML += strAddress;
                             strHTML += "<br>";
                         }
@@ -1407,11 +1407,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Mixed debit transaction
                 //
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                    if (txin.IsMine())
-                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
+                    if (pwalletMain->IsMine(txin))
+                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    if (txout.IsMine())
-                        strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
+                    if (pwalletMain->IsMine(txout))
+                        strHTML += _("<b>Credit:</b> ") + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
             }
         }
 
@@ -1437,30 +1437,30 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             strHTML += "<hr><br>debug print<br><br>";
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                if (txin.IsMine())
-                    strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
+                if (pwalletMain->IsMine(txin))
+                    strHTML += "<b>Debit:</b> " + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                if (txout.IsMine())
-                    strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
+                if (pwalletMain->IsMine(txout))
+                    strHTML += "<b>Credit:</b> " + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
 
             strHTML += "<br><b>Transaction:</b><br>";
             strHTML += HtmlEscape(wtx.ToString(), true);
 
             strHTML += "<br><b>Inputs:</b><br>";
-            CRITICAL_BLOCK(cs_mapWallet)
+            CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
                 {
                     COutPoint prevout = txin.prevout;
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(prevout.hash);
+                    if (mi != pwalletMain->mapWallet.end())
                     {
                         const CWalletTx& prev = (*mi).second;
                         if (prevout.n < prev.vout.size())
                         {
                             strHTML += HtmlEscape(prev.ToString(), true);
                             strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", ";
-                            strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
+                            strHTML = strHTML + "IsMine=" + (pwalletMain->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "<br>";
                         }
                     }
                 }
@@ -1751,7 +1751,7 @@ void COptionsDialog::OnButtonCancel(wxCommandEvent& event)
 
 void COptionsDialog::OnButtonApply(wxCommandEvent& event)
 {
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
 
     int64 nPrevTransactionFee = nTransactionFee;
     if (ParseMoney(m_textCtrlTransactionFee->GetValue(), nTransactionFee) && nTransactionFee != nPrevTransactionFee)
@@ -1928,12 +1928,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
             wxMessageBox(_("Error in amount  "), _("Send Coins"));
             return;
         }
-        if (nValue > GetBalance())
+        if (nValue > pwalletMain->GetBalance())
         {
             wxMessageBox(_("Amount exceeds your balance  "), _("Send Coins"));
             return;
         }
-        if (nValue + nTransactionFee > GetBalance())
+        if (nValue + nTransactionFee > pwalletMain->GetBalance())
         {
             wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included  "), _("Send Coins"));
             return;
@@ -1951,7 +1951,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
                 CScript scriptPubKey;
                 scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
 
-                string strError = SendMoney(scriptPubKey, nValue, wtx, true);
+                string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
                 if (strError == "")
                     wxMessageBox(_("Payment sent  "), _("Sending..."));
                 else if (strError == "ABORTED")
@@ -1983,9 +1983,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
                 return;
         }
 
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            if (!mapAddressBook.count(strAddress))
-                SetAddressBookName(strAddress, "");
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+            if (!pwalletMain->mapAddressBook.count(strAddress))
+                pwalletMain->SetAddressBookName(strAddress, "");
 
         EndModal(true);
     }
@@ -2169,7 +2169,7 @@ void SendingDialogStartTransfer(void* parg)
 void CSendingDialog::StartTransfer()
 {
     // Make sure we have enough money
-    if (nPrice + nTransactionFee > GetBalance())
+    if (nPrice + nTransactionFee > pwalletMain->GetBalance())
     {
         Error(_("Insufficient funds"));
         return;
@@ -2240,16 +2240,16 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
         // Pay
         if (!Status(_("Creating transaction...")))
             return;
-        if (nPrice + nTransactionFee > GetBalance())
+        if (nPrice + nTransactionFee > pwalletMain->GetBalance())
         {
             Error(_("Insufficient funds"));
             return;
         }
-        CReserveKey reservekey;
+        CReserveKey reservekey(pwalletMain);
         int64 nFeeRequired;
-        if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
+        if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
         {
-            if (nPrice + nFeeRequired > GetBalance())
+            if (nPrice + nFeeRequired > pwalletMain->GetBalance())
                 Error(strprintf(_("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()));
             else
                 Error(_("Transaction creation failed"));
@@ -2287,7 +2287,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
             return;
 
         // Commit
-        if (!CommitTransaction(wtx, reservekey))
+        if (!pwalletMain->CommitTransaction(wtx, reservekey))
         {
             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."));
             return;
@@ -2381,11 +2381,11 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
     m_listCtrlReceiving->SetFocus();
 
     // Fill listctrl with address book data
-    CRITICAL_BLOCK(cs_mapKeys)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapKeys)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             string strAddress = item.first;
             string strName = item.second;
@@ -2444,7 +2444,7 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
     if (event.IsEditCancelled())
         return;
     string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
-    SetAddressBookName(strAddress, string(event.GetText()));
+    pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
     pframeMain->RefreshListCtrl();
 }
 
@@ -2479,7 +2479,7 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
         if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
         {
             string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
-            CWalletDB().EraseName(strAddress);
+            CWalletDB(pwalletMain->strWalletFile).EraseName(strAddress);
             m_listCtrl->DeleteItem(nIndex);
         }
     }
@@ -2539,8 +2539,8 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
 
     // Write back
     if (strAddress != strAddressOrg)
-        CWalletDB().EraseName(strAddressOrg);
-    SetAddressBookName(strAddress, strName);
+        CWalletDB(pwalletMain->strWalletFile).EraseName(strAddressOrg);
+    pwalletMain->SetAddressBookName(strAddress, strName);
     m_listCtrl->SetItem(nIndex, 1, strAddress);
     m_listCtrl->SetItemText(nIndex, strName);
     pframeMain->RefreshListCtrl();
@@ -2576,11 +2576,11 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
         strName = dialog.GetValue();
 
         // Generate new key
-        strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+        strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
     }
 
     // Add to list and select it
-    SetAddressBookName(strAddress, strName);
+    pwalletMain->SetAddressBookName(strAddress, strName);
     int nIndex = InsertLine(m_listCtrl, strName, strAddress);
     SetSelection(m_listCtrl, nIndex);
     m_listCtrl->SetFocus();
index a9fc92f..aef8d18 100644 (file)
@@ -15,29 +15,40 @@ using namespace std;
 // mapWallet
 //
 
-void WalletUpdateSpent(const COutPoint& prevout)
+bool CWallet::AddKey(const CKey& key)
+{
+    this->CKeyStore::AddKey(key);
+    if (!fFileBacked)
+        return true;
+    return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
+}
+
+void CWallet::WalletUpdateSpent(const CTransaction &tx)
 {
     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
     // Update the wallet spent flag if it doesn't know due to wallet.dat being
     // restored from backup or the user making copies of wallet.dat.
     CRITICAL_BLOCK(cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-        if (mi != mapWallet.end())
+        BOOST_FOREACH(const CTxIn& txin, tx.vin)
         {
-            CWalletTx& wtx = (*mi).second;
-            if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine())
+            map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
+            if (mi != mapWallet.end())
             {
-                printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
-                wtx.MarkSpent(prevout.n);
-                wtx.WriteToDisk();
-                vWalletUpdated.push_back(prevout.hash);
+                CWalletTx& wtx = (*mi).second;
+                if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
+                {
+                    printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+                    wtx.MarkSpent(txin.prevout.n);
+                    wtx.WriteToDisk();
+                    vWalletUpdated.push_back(txin.prevout.hash);
+                }
             }
         }
     }
 }
 
-bool AddToWallet(const CWalletTx& wtxIn)
+bool CWallet::AddToWallet(const CWalletTx& wtxIn)
 {
     uint256 hash = wtxIn.GetHash();
     CRITICAL_BLOCK(cs_mapWallet)
@@ -45,6 +56,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
         // Inserts only if not already there, returns tx inserted or tx found
         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
         CWalletTx& wtx = (*ret.first).second;
+        wtx.pwallet = this;
         bool fInsertedNew = ret.second;
         if (fInsertedNew)
             wtx.nTimeReceived = GetAdjustedTime();
@@ -87,7 +99,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
         {
             if (txout.scriptPubKey == scriptDefaultKey)
             {
-                CWalletDB walletdb;
+                if (!fFileBacked)
+                    continue;
+                CWalletDB walletdb(strWalletFile);
                 vchDefaultKey = GetKeyFromKeyPool();
                 walletdb.WriteDefaultKey(vchDefaultKey);
                 walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
@@ -96,6 +110,9 @@ bool AddToWallet(const CWalletTx& wtxIn)
 
         // Notify UI
         vWalletUpdated.push_back(hash);
+
+        // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
+        WalletUpdateSpent(wtx);
     }
 
     // Refresh UI
@@ -103,60 +120,64 @@ bool AddToWallet(const CWalletTx& wtxIn)
     return true;
 }
 
-bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
 {
     uint256 hash = tx.GetHash();
     bool fExisted = mapWallet.count(hash);
     if (fExisted && !fUpdate) return false;
-    if (fExisted || tx.IsMine() || tx.IsFromMe())
+    if (fExisted || IsMine(tx) || IsFromMe(tx))
     {
-        CWalletTx wtx(tx);
+        CWalletTx wtx(this,tx);
         // Get merkle branch if transaction was found in a block
         if (pblock)
             wtx.SetMerkleBranch(pblock);
         return AddToWallet(wtx);
     }
+    else
+        WalletUpdateSpent(tx);
     return false;
 }
 
-bool EraseFromWallet(uint256 hash)
+bool CWallet::EraseFromWallet(uint256 hash)
 {
+    if (!fFileBacked)
+        return false;
     CRITICAL_BLOCK(cs_mapWallet)
     {
         if (mapWallet.erase(hash))
-            CWalletDB().EraseTx(hash);
+            CWalletDB(strWalletFile).EraseTx(hash);
     }
     return true;
 }
 
 
-bool CTxIn::IsMine() const
+bool CWallet::IsMine(const CTxIn &txin) const
 {
     CRITICAL_BLOCK(cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
+        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
         if (mi != mapWallet.end())
         {
             const CWalletTx& prev = (*mi).second;
-            if (prevout.n < prev.vout.size())
-                if (prev.vout[prevout.n].IsMine())
+            if (txin.prevout.n < prev.vout.size())
+                if (IsMine(prev.vout[txin.prevout.n]))
                     return true;
         }
     }
     return false;
 }
 
-int64 CTxIn::GetDebit() const
+int64 CWallet::GetDebit(const CTxIn &txin) const
 {
     CRITICAL_BLOCK(cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
+        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
         if (mi != mapWallet.end())
         {
             const CWalletTx& prev = (*mi).second;
-            if (prevout.n < prev.vout.size())
-                if (prev.vout[prevout.n].IsMine())
-                    return prev.vout[prevout.n].nValue;
+            if (txin.prevout.n < prev.vout.size())
+                if (IsMine(prev.vout[txin.prevout.n]))
+                    return prev.vout[txin.prevout.n].nValue;
         }
     }
     return 0;
@@ -184,31 +205,31 @@ int CWalletTx::GetRequestCount() const
 {
     // Returns -1 if it wasn't being tracked
     int nRequests = -1;
-    CRITICAL_BLOCK(cs_mapRequestCount)
+    CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
     {
         if (IsCoinBase())
         {
             // Generated block
             if (hashBlock != 0)
             {
-                map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
-                if (mi != mapRequestCount.end())
+                map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                if (mi != pwallet->mapRequestCount.end())
                     nRequests = (*mi).second;
             }
         }
         else
         {
             // Did anyone request this transaction?
-            map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
-            if (mi != mapRequestCount.end())
+            map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
+            if (mi != pwallet->mapRequestCount.end())
             {
                 nRequests = (*mi).second;
 
                 // How about the block it's in?
                 if (nRequests == 0 && hashBlock != 0)
                 {
-                    map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
-                    if (mi != mapRequestCount.end())
+                    map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                    if (mi != pwallet->mapRequestCount.end())
                         nRequests = (*mi).second;
                     else
                         nRequests = 1; // If it's in someone else's block it must have got out
@@ -230,7 +251,7 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
     if (IsCoinBase())
     {
         if (GetBlocksToMaturity() > 0)
-            nGeneratedImmature = CTransaction::GetCredit();
+            nGeneratedImmature = pwallet->GetCredit(*this);
         else
             nGeneratedMature = GetCredit();
         return;
@@ -263,13 +284,13 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
         }
 
         // Don't report 'change' txouts
-        if (nDebit > 0 && txout.IsChange())
+        if (nDebit > 0 && pwallet->IsChange(txout))
             continue;
 
         if (nDebit > 0)
             listSent.push_back(make_pair(address, txout.nValue));
 
-        if (txout.IsMine())
+        if (pwallet->IsMine(txout))
             listReceived.push_back(make_pair(address, txout.nValue));
     }
 
@@ -295,16 +316,15 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
             nSent += s.second;
         nFee = allFee;
     }
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
     {
         BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
         {
-            if (mapAddressBook.count(r.first))
+            if (pwallet->mapAddressBook.count(r.first))
             {
-                if (mapAddressBook[r.first] == strAccount)
-                {
+                map<string, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
+                if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
                     nReceived += r.second;
-                }
             }
             else if (strAccount.empty())
             {
@@ -326,7 +346,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
             vWorkQueue.push_back(txin.prevout.hash);
 
         // This critsect is OK because txdb is already open
-        CRITICAL_BLOCK(cs_mapWallet)
+        CRITICAL_BLOCK(pwallet->cs_mapWallet)
         {
             map<uint256, const CMerkleTx*> mapWalletPrev;
             set<uint256> setAlreadyDone;
@@ -338,10 +358,11 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
                 setAlreadyDone.insert(hash);
 
                 CMerkleTx tx;
-                if (mapWallet.count(hash))
+                map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
+                if (mi != pwallet->mapWallet.end())
                 {
-                    tx = mapWallet[hash];
-                    BOOST_FOREACH(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
+                    tx = (*mi).second;
+                    BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
                 }
                 else if (mapWalletPrev.count(hash))
@@ -373,10 +394,10 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
 
 bool CWalletTx::WriteToDisk()
 {
-    return CWalletDB().WriteTx(GetHash(), *this);
+    return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
 }
 
-int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
+int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
 {
     int ret = 0;
 
@@ -398,7 +419,7 @@ int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
     return ret;
 }
 
-void ReacceptWalletTransactions()
+void CWallet::ReacceptWalletTransactions()
 {
     CTxDB txdb("r");
     bool fRepeat = true;
@@ -426,7 +447,7 @@ void ReacceptWalletTransactions()
                 {
                     if (wtx.IsSpent(i))
                         continue;
-                    if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
+                    if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
                     {
                         wtx.MarkSpent(i);
                         fUpdated = true;
@@ -484,7 +505,7 @@ void CWalletTx::RelayWalletTransaction()
    RelayWalletTransaction(txdb);
 }
 
-void ResendWalletTransactions()
+void CWallet::ResendWalletTransactions()
 {
     // Do this infrequently and randomly to avoid giving away
     // that these are our transactions.
@@ -536,16 +557,16 @@ void ResendWalletTransactions()
 //
 
 
-int64 GetBalance()
+int64 CWallet::GetBalance() const
 {
     int64 nStart = GetTimeMillis();
 
     int64 nTotal = 0;
     CRITICAL_BLOCK(cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
         {
-            CWalletTx* pcoin = &(*it).second;
+            const CWalletTx* pcoin = &(*it).second;
             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
                 continue;
             nTotal += pcoin->GetAvailableCredit();
@@ -557,27 +578,27 @@ int64 GetBalance()
 }
 
 
-bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
+bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
 {
     setCoinsRet.clear();
     nValueRet = 0;
 
     // List of values less than target
-    pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger;
+    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
     coinLowestLarger.first = INT64_MAX;
     coinLowestLarger.second.first = NULL;
-    vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue;
+    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
     int64 nTotalLower = 0;
 
     CRITICAL_BLOCK(cs_mapWallet)
     {
-       vector<CWalletTx*> vCoins;
+       vector<const CWalletTx*> vCoins;
        vCoins.reserve(mapWallet.size());
-       for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+       for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
            vCoins.push_back(&(*it).second);
        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
 
-       BOOST_FOREACH(CWalletTx* pcoin, vCoins)
+       BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
        {
             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
                 continue;
@@ -591,7 +612,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
 
             for (int i = 0; i < pcoin->vout.size(); i++)
             {
-                if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine())
+                if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
                     continue;
 
                 int64 n = pcoin->vout[i].nValue;
@@ -599,7 +620,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
                 if (n <= 0)
                     continue;
 
-                pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
+                pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
 
                 if (n == nTargetValue)
                 {
@@ -702,7 +723,7 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<
     return true;
 }
 
-bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
+bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
 {
     return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
             SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
@@ -712,7 +733,7 @@ bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoi
 
 
 
-bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
 {
     int64 nValue = 0;
     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
@@ -724,6 +745,8 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
     if (vecSend.empty() || nValue < 0)
         return false;
 
+    wtxNew.pwallet = this;
+
     CRITICAL_BLOCK(cs_main)
     {
         // txdb must be opened before the mapWallet lock
@@ -744,11 +767,11 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
 
                 // Choose coins to use
-                set<pair<CWalletTx*,unsigned int> > setCoins;
+                set<pair<const CWalletTx*,unsigned int> > setCoins;
                 int64 nValueIn = 0;
                 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
                     return false;
-                BOOST_FOREACH(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins)
+                BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
                 {
                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
@@ -784,13 +807,13 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
                     reservekey.ReturnKey();
 
                 // Fill vin
-                BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
+                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
 
                 // Sign
                 int nIn = 0;
-                BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
-                    if (!SignSignature(*coin.first, wtxNew, nIn++))
+                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+                    if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
                         return false;
 
                 // Limit size
@@ -820,7 +843,7 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx&
     return true;
 }
 
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
 {
     vector< pair<CScript, int64> > vecSend;
     vecSend.push_back(make_pair(scriptPubKey, nValue));
@@ -828,7 +851,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR
 }
 
 // Call after CreateTransaction unless you want to abort
-bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
+bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
 {
     CRITICAL_BLOCK(cs_main)
     {
@@ -838,7 +861,7 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
             // This is only to keep the database open to defeat the auto-flush for the
             // duration of this scope.  This is the only place where this optimization
             // maybe makes sense; please don't do it anywhere else.
-            CWalletDB walletdb("r");
+            CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
 
             // Take key pair from key pool so it won't be used again
             reservekey.KeepKey();
@@ -851,11 +874,15 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
             set<CWalletTx*> setCoins;
             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
             {
-                CWalletTx &pcoin = mapWallet[txin.prevout.hash];
-                pcoin.MarkSpent(txin.prevout.n);
-                pcoin.WriteToDisk();
-                vWalletUpdated.push_back(pcoin.GetHash());
+                CWalletTx &coin = mapWallet[txin.prevout.hash];
+                coin.pwallet = this;
+                coin.MarkSpent(txin.prevout.n);
+                coin.WriteToDisk();
+                vWalletUpdated.push_back(coin.GetHash());
             }
+
+            if (fFileBacked)
+                delete pwalletdb;
         }
 
         // Track how many getdata requests our transaction gets
@@ -879,9 +906,9 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
 
 
 // requires cs_main lock
-string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
+string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
 {
-    CReserveKey reservekey;
+    CReserveKey reservekey(this);
     int64 nFeeRequired;
     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
     {
@@ -907,7 +934,7 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
 
 
 // requires cs_main lock
-string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
+string CWallet::SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
 {
     // Check amount
     if (nValue <= 0)
@@ -926,10 +953,12 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
 
 
 
-bool LoadWallet(bool& fFirstRunRet)
+bool CWallet::LoadWallet(bool& fFirstRunRet)
 {
+    if (!fFileBacked)
+        return false;
     fFirstRunRet = false;
-    if (!CWalletDB("cr+").LoadWallet())
+    if (!CWalletDB(strWalletFile,"cr+").LoadWallet(this))
         return false;
     fFirstRunRet = vchDefaultKey.empty();
 
@@ -944,17 +973,52 @@ bool LoadWallet(bool& fFirstRunRet)
         // Create new keyUser and set as default key
         RandAddSeedPerfmon();
 
-        CWalletDB walletdb;
         vchDefaultKey = GetKeyFromKeyPool();
-        walletdb.WriteDefaultKey(vchDefaultKey);
-        walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
+        if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
+            return false;
+        CWalletDB(strWalletFile).WriteDefaultKey(keyUser.GetPubKey());
     }
 
-    CreateThread(ThreadFlushWalletDB, NULL);
+    CreateThread(ThreadFlushWalletDB, &strWalletFile);
     return true;
 }
 
-void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
+void CWallet::PrintWallet(const CBlock& block)
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        if (mapWallet.count(block.vtx[0].GetHash()))
+        {
+            CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
+            printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+        }
+    }
+    printf("\n");
+}
+
+bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
+        if (mi != mapWallet.end())
+        {
+            wtx = (*mi).second;
+            return true;
+        }
+        return false;
+    }
+}
+
+bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
+{
+    if (!pwallet->fFileBacked)
+        return false;
+    strWalletFileOut = pwallet->strWalletFile;
+    return true;
+}
+
+void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 {
     nIndex = -1;
     keypool.vchPubKey.clear();
@@ -962,6 +1026,8 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
     CRITICAL_BLOCK(cs_mapWallet)
     CRITICAL_BLOCK(cs_setKeyPool)
     {
+        CWalletDB walletdb(strWalletFile);
+
         // Top up key pool
         int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
         while (setKeyPool.size() < nTargetSize+1)
@@ -969,7 +1035,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
             int64 nEnd = 1;
             if (!setKeyPool.empty())
                 nEnd = *(--setKeyPool.end()) + 1;
-            if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
+            if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
                 throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
             setKeyPool.insert(nEnd);
             printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
@@ -979,7 +1045,7 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
         assert(!setKeyPool.empty());
         nIndex = *(setKeyPool.begin());
         setKeyPool.erase(setKeyPool.begin());
-        if (!Read(make_pair(string("pool"), nIndex), keypool))
+        if (!walletdb.ReadPool(nIndex, keypool))
             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
         if (!mapKeys.count(keypool.vchPubKey))
             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
@@ -988,18 +1054,21 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
     }
 }
 
-void CWalletDB::KeepKey(int64 nIndex)
+void CWallet::KeepKey(int64 nIndex)
 {
     // Remove from key pool
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    if (fFileBacked)
     {
-        Erase(make_pair(string("pool"), nIndex));
+        CWalletDB walletdb(strWalletFile);
+        CRITICAL_BLOCK(cs_main)
+        {
+            walletdb.ErasePool(nIndex);
+        }
     }
     printf("keypool keep %"PRI64d"\n", nIndex);
 }
 
-void CWalletDB::ReturnKey(int64 nIndex)
+void CWallet::ReturnKey(int64 nIndex)
 {
     // Return to key pool
     CRITICAL_BLOCK(cs_setKeyPool)
@@ -1007,32 +1076,30 @@ void CWalletDB::ReturnKey(int64 nIndex)
     printf("keypool return %"PRI64d"\n", nIndex);
 }
 
-vector<unsigned char> GetKeyFromKeyPool()
+vector<unsigned char> CWallet::GetKeyFromKeyPool()
 {
-    CWalletDB walletdb;
     int64 nIndex = 0;
     CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.KeepKey(nIndex);
+    ReserveKeyFromKeyPool(nIndex, keypool);
+    KeepKey(nIndex);
     return keypool.vchPubKey;
 }
 
-int64 GetOldestKeyPoolTime()
+int64 CWallet::GetOldestKeyPoolTime()
 {
-    CWalletDB walletdb;
     int64 nIndex = 0;
     CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.ReturnKey(nIndex);
+    ReserveKeyFromKeyPool(nIndex, keypool);
+    ReturnKey(nIndex);
     return keypool.nTime;
 }
 
-std::vector<unsigned char> CReserveKey::GetReservedKey()
+vector<unsigned char> CReserveKey::GetReservedKey()
 {
     if (nIndex == -1)
     {
         CKeyPool keypool;
-        CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
+        pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
         vchPubKey = keypool.vchPubKey;
     }
     assert(!vchPubKey.empty());
@@ -1042,7 +1109,7 @@ std::vector<unsigned char> CReserveKey::GetReservedKey()
 void CReserveKey::KeepKey()
 {
     if (nIndex != -1)
-        CWalletDB().KeepKey(nIndex);
+        pwallet->KeepKey(nIndex);
     nIndex = -1;
     vchPubKey.clear();
 }
@@ -1050,7 +1117,7 @@ void CReserveKey::KeepKey()
 void CReserveKey::ReturnKey()
 {
     if (nIndex != -1)
-        CWalletDB::ReturnKey(nIndex);
+        pwallet->ReturnKey(nIndex);
     nIndex = -1;
     vchPubKey.clear();
 }
index f9d2ea0..b14a2e8 100644 (file)
 #define BITCOIN_WALLET_H
 
 #include "bignum.h"
+#include "key.h"
 #include "script.h"
 
 class CWalletTx;
 class CReserveKey;
 class CWalletDB;
 
-extern std::map<uint256, CWalletTx> mapWallet;
-extern std::vector<uint256> vWalletUpdated;
-extern CCriticalSection cs_mapWallet;
+class CWallet : public CKeyStore
+{
+private:
+    bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
+    bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
 
-extern std::map<uint256, int> mapRequestCount;
-extern CCriticalSection cs_mapRequestCount;
 
-extern std::map<std::string, std::string> mapAddressBook;
-extern CCriticalSection cs_mapAddressBook;
+public:
+    bool fFileBacked;
+    std::string strWalletFile;
 
-extern std::vector<unsigned char> vchDefaultKey;
-extern CKey keyUser;
+    std::set<int64> setKeyPool;
+    CCriticalSection cs_setKeyPool;
 
-bool AddToWallet(const CWalletTx& wtxIn);
-bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
-bool EraseFromWallet(uint256 hash);
-void WalletUpdateSpent(const COutPoint& prevout);
-int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
-void ReacceptWalletTransactions();
-void ResendWalletTransactions();
-int64 GetBalance();
-bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
-bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
-bool BroadcastTransaction(CWalletTx& wtxNew);
-std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
-std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
+    CWallet()
+    {
+        fFileBacked = false;
+    }
+    CWallet(std::string strWalletFileIn)
+    {
+        strWalletFile = strWalletFileIn;
+        fFileBacked = true;
+    }
 
+    mutable CCriticalSection cs_mapWallet;
+    std::map<uint256, CWalletTx> mapWallet;
+    std::vector<uint256> vWalletUpdated;
+
+    std::map<uint256, int> mapRequestCount;
+    mutable CCriticalSection cs_mapRequestCount;
+
+    std::map<std::string, std::string> mapAddressBook;
+    mutable CCriticalSection cs_mapAddressBook;
+
+    std::vector<unsigned char> vchDefaultKey;
+    CKey keyUser;
+
+    bool AddKey(const CKey& key);
+    bool AddToWallet(const CWalletTx& wtxIn);
+    bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
+    bool EraseFromWallet(uint256 hash);
+    void WalletUpdateSpent(const CTransaction& prevout);
+    int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
+    void ReacceptWalletTransactions();
+    void ResendWalletTransactions();
+    int64 GetBalance() const;
+    bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
+    bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
+    bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
+    bool BroadcastTransaction(CWalletTx& wtxNew);
+    std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
+    std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
+
+    void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
+    void KeepKey(int64 nIndex);
+    void ReturnKey(int64 nIndex);
+    std::vector<unsigned char> GetKeyFromKeyPool();
+    int64 GetOldestKeyPoolTime();
+
+    bool IsMine(const CTxIn& txin) const;
+    int64 GetDebit(const CTxIn& txin) const;
+    bool IsMine(const CTxOut& txout) const
+    {
+        return ::IsMine(*this, txout.scriptPubKey);
+    }
+    int64 GetCredit(const CTxOut& txout) const
+    {
+        if (!MoneyRange(txout.nValue))
+            throw std::runtime_error("CWallet::GetCredit() : value out of range");
+        return (IsMine(txout) ? txout.nValue : 0);
+    }
+    bool IsChange(const CTxOut& txout) const
+    {
+        std::vector<unsigned char> vchPubKey;
+        if (ExtractPubKey(txout.scriptPubKey, this, vchPubKey))
+            CRITICAL_BLOCK(cs_mapAddressBook)
+                if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
+                    return true;
+        return false;
+    }
+    int64 GetChange(const CTxOut& txout) const
+    {
+        if (!MoneyRange(txout.nValue))
+            throw std::runtime_error("CWallet::GetChange() : value out of range");
+        if (IsChange(txout) ? txout.nValue : 0);
+    }
+    bool IsMine(const CTransaction& tx) const
+    {
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+            if (IsMine(txout))
+                return true;
+        return false;
+    }
+    bool IsFromMe(const CTransaction& tx) const
+    {
+        return (GetDebit(tx) > 0);
+    }
+    int64 GetDebit(const CTransaction& tx) const
+    {
+        int64 nDebit = 0;
+        BOOST_FOREACH(const CTxIn& txin, tx.vin)
+        {
+            nDebit += GetDebit(txin);
+            if (!MoneyRange(nDebit))
+                throw std::runtime_error("CWallet::GetDebit() : value out of range");
+        }
+        return nDebit;
+    }
+    int64 GetCredit(const CTransaction& tx) const
+    {
+        int64 nCredit = 0;
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+        {
+            nCredit += GetCredit(txout);
+            if (!MoneyRange(nCredit))
+                throw std::runtime_error("CWallet::GetCredit() : value out of range");
+        }
+        return nCredit;
+    }
+    int64 GetChange(const CTransaction& tx) const
+    {
+        int64 nChange = 0;
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+        {
+            nChange += GetChange(txout);
+            if (!MoneyRange(nChange))
+                throw std::runtime_error("CWallet::GetChange() : value out of range");
+        }
+        return nChange;
+    }
+    void SetBestChain(const CBlockLocator& loc)
+    {
+        CWalletDB walletdb(strWalletFile);
+        walletdb.WriteBestBlock(loc);
+    }
+
+    bool LoadWallet(bool& fFirstRunRet);
+//    bool BackupWallet(const std::string& strDest);
+
+    bool SetAddressBookName(const std::string& strAddress, const std::string& strName)
+    {
+        if (!fFileBacked)
+            return false;
+        return CWalletDB(strWalletFile).WriteName(strAddress, strName);
+    }
+
+    void UpdatedTransaction(const uint256 &hashTx)
+    {
+        CRITICAL_BLOCK(cs_mapWallet)
+            vWalletUpdated.push_back(hashTx);
+    }
+
+    void PrintWallet(const CBlock& block);
+
+    void Inventory(const uint256 &hash)
+    {
+        CRITICAL_BLOCK(cs_mapRequestCount)
+        {
+            std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
+            if (mi != mapRequestCount.end())
+                (*mi).second++;
+        }
+    }
+
+    bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
+
+};
+
+
+class CReserveKey
+{
+protected:
+    CWallet* pwallet;
+    int64 nIndex;
+    std::vector<unsigned char> vchPubKey;
+public:
+    CReserveKey(CWallet* pwalletIn)
+    {
+        nIndex = -1;
+        pwallet = pwalletIn;
+    }
+
+    ~CReserveKey()
+    {
+        if (!fShutdown)
+            ReturnKey();
+    }
+
+    void ReturnKey();
+    std::vector<unsigned char> GetReservedKey();
+    void KeepKey();
+};
 
 
 //
@@ -49,6 +214,8 @@ std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWal
 class CWalletTx : public CMerkleTx
 {
 public:
+    const CWallet* pwallet;
+
     std::vector<CMerkleTx> vtxPrev;
     std::map<std::string, std::string> mapValue;
     std::vector<std::pair<std::string, std::string> > vOrderForm;
@@ -73,24 +240,29 @@ public:
     mutable int nLinesDisplayed;
     mutable char fConfirmedDisplayed;
 
-
     CWalletTx()
     {
-        Init();
+        Init(NULL);
     }
 
-    CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
+    CWalletTx(const CWallet* pwalletIn)
     {
-        Init();
+        Init(pwalletIn);
     }
 
-    CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
+    CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
     {
-        Init();
+        Init(pwalletIn);
     }
 
-    void Init()
+    CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
     {
+        Init(pwalletIn);
+    }
+
+    void Init(const CWallet* pwalletIn)
+    {
+        pwallet = pwalletIn;
         vtxPrev.clear();
         mapValue.clear();
         vOrderForm.clear();
@@ -116,7 +288,7 @@ public:
     (
         CWalletTx* pthis = const_cast<CWalletTx*>(this);
         if (fRead)
-            pthis->Init();
+            pthis->Init(NULL);
         char fSpent = false;
 
         if (!fRead)
@@ -213,7 +385,7 @@ public:
             return 0;
         if (fDebitCached)
             return nDebitCached;
-        nDebitCached = CTransaction::GetDebit();
+        nDebitCached = pwallet->GetDebit(*this);
         fDebitCached = true;
         return nDebitCached;
     }
@@ -227,7 +399,7 @@ public:
         // GetBalance can assume transactions in mapWallet won't change
         if (fUseCache && fCreditCached)
             return nCreditCached;
-        nCreditCached = CTransaction::GetCredit();
+        nCreditCached = pwallet->GetCredit(*this);
         fCreditCached = true;
         return nCreditCached;
     }
@@ -247,7 +419,7 @@ public:
             if (!IsSpent(i))
             {
                 const CTxOut &txout = vout[i];
-                nCredit += txout.GetCredit();
+                nCredit += pwallet->GetCredit(txout);
                 if (!MoneyRange(nCredit))
                     throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
             }
@@ -263,7 +435,7 @@ public:
     {
         if (fChangeCached)
             return nChangeCached;
-        nChangeCached = CTransaction::GetChange();
+        nChangeCached = pwallet->GetChange(*this);
         fChangeCached = true;
         return nChangeCached;
     }
@@ -271,7 +443,7 @@ public:
     void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<std::string /* address */, int64> >& listReceived,
                     std::list<std::pair<std::string /* address */, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
 
-    void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
+    void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, 
                            int64& nSent, int64& nFee) const;
 
     bool IsFromMe() const
@@ -303,7 +475,7 @@ public:
                 return false;
             if (ptx->GetDepthInMainChain() >= 1)
                 continue;
-            if (!ptx->IsFromMe())
+            if (!pwallet->IsFromMe(*ptx))
                 return false;
 
             if (mapPrev.empty())
@@ -438,4 +610,6 @@ public:
     )
 };
 
+bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
+
 #endif