Remove wxWidgets
[novacoin.git] / src / db.cpp
index c2c239d..f236364 100644 (file)
@@ -1,14 +1,17 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2011 The Bitcoin developers
 // Distributed under the MIT/X11 software license, see the accompanying
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "db.h"
+#include "net.h"
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 
 using namespace std;
 using namespace boost;
 
-void ThreadFlushWalletDB(void* parg);
-
 
 unsigned int nWalletDBUpdated;
 uint64 nAccountingEntryNumber = 0;
@@ -147,7 +150,7 @@ void CDB::Close()
         --mapFileUseCount[strFile];
 }
 
-void CloseDb(const string& strFile)
+void static CloseDb(const string& strFile)
 {
     CRITICAL_BLOCK(cs_db)
     {
@@ -356,7 +359,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;
@@ -526,7 +529,7 @@ bool CAddrDB::LoadAddresses()
                 char psz[1000];
                 while (fgets(psz, sizeof(psz), filein))
                 {
-                    CAddress addr(psz, NODE_NETWORK);
+                    CAddress addr(psz, false, NODE_NETWORK);
                     addr.nTime = 0; // so it won't relay unless successfully connected
                     if (addr.IsValid())
                         AddAddress(addr);
@@ -581,8 +584,19 @@ bool LoadAddresses()
 // CWalletDB
 //
 
-static set<int64> setKeyPool;
-static CCriticalSection cs_setKeyPool;
+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)
 {
@@ -597,7 +611,7 @@ bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
 
 bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
 {
-    return Write(make_tuple(string("acentry"), acentry.strAccount, ++nAccountingEntryNumber), acentry);
+    return Write(boost::make_tuple(string("acentry"), acentry.strAccount, ++nAccountingEntryNumber), acentry);
 }
 
 int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
@@ -614,8 +628,6 @@ int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
 
 void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
 {
-    int64 nCreditDebit = 0;
-
     bool fAllAccounts = (strAccount == "*");
 
     Dbc* pcursor = GetCursor();
@@ -627,7 +639,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
         // Read next record
         CDataStream ssKey;
         if (fFlags == DB_SET_RANGE)
-            ssKey << make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
+            ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
         CDataStream ssValue;
         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
         fFlags = DB_NEXT;
@@ -657,9 +669,9 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
 }
 
 
-bool CWalletDB::LoadWallet()
+int CWalletDB::LoadWallet(CWallet* pwallet)
 {
-    vchDefaultKey.clear();
+    pwallet->vchDefaultKey.clear();
     int nFileVersion = 0;
     vector<uint256> vWalletUpgrade;
 
@@ -671,13 +683,12 @@ 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_wallet)
     {
         // Get cursor
         Dbc* pcursor = GetCursor();
         if (!pcursor)
-            return false;
+            return DB_CORRUPT;
 
         loop
         {
@@ -688,7 +699,7 @@ bool CWalletDB::LoadWallet()
             if (ret == DB_NOTFOUND)
                 break;
             else if (ret != 0)
-                return false;
+                return DB_CORRUPT;
 
             // Unserialize
             // Taking advantage of the fact that pair serialization
@@ -699,14 +710,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");
@@ -751,24 +763,52 @@ bool CWalletDB::LoadWallet()
             {
                 vector<unsigned char> vchPubKey;
                 ssKey >> vchPubKey;
-                CWalletKey wkey;
+                CKey key;
                 if (strType == "key")
-                    ssValue >> wkey.vchPrivKey;
+                {
+                    CPrivKey pkey;
+                    ssValue >> pkey;
+                    key.SetPrivKey(pkey);
+                }
                 else
+                {
+                    CWalletKey wkey;
                     ssValue >> wkey;
-
-                mapKeys[vchPubKey] = wkey.vchPrivKey;
-                mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
+                    key.SetPrivKey(wkey.vchPrivKey);
+                }
+                if (!pwallet->LoadKey(key))
+                    return DB_CORRUPT;
+            }
+            else if (strType == "mkey")
+            {
+                unsigned int nID;
+                ssKey >> nID;
+                CMasterKey kMasterKey;
+                ssValue >> kMasterKey;
+                if(pwallet->mapMasterKeys.count(nID) != 0)
+                    return DB_CORRUPT;
+                pwallet->mapMasterKeys[nID] = kMasterKey;
+                if (pwallet->nMasterKeyMaxID < nID)
+                    pwallet->nMasterKeyMaxID = nID;
+            }
+            else if (strType == "ckey")
+            {
+                vector<unsigned char> vchPubKey;
+                ssKey >> vchPubKey;
+                vector<unsigned char> vchPrivKey;
+                ssValue >> vchPrivKey;
+                if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
+                    return DB_CORRUPT;
             }
             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")
             {
@@ -782,11 +822,10 @@ bool CWalletDB::LoadWallet()
                 ssKey >> strKey;
 
                 // Options
-#ifndef GUI
+#ifndef QT_GUI
                 if (strKey == "fGenerateBitcoins")  ssValue >> fGenerateBitcoins;
 #endif
                 if (strKey == "nTransactionFee")    ssValue >> nTransactionFee;
-                if (strKey == "addrIncoming")       ssValue >> addrIncoming;
                 if (strKey == "fLimitProcessors")   ssValue >> fLimitProcessors;
                 if (strKey == "nLimitProcessors")   ssValue >> nLimitProcessors;
                 if (strKey == "fMinimizeToTray")    ssValue >> fMinimizeToTray;
@@ -795,17 +834,23 @@ bool CWalletDB::LoadWallet()
                 if (strKey == "addrProxy")          ssValue >> addrProxy;
                 if (fHaveUPnP && strKey == "fUseUPnP")           ssValue >> fUseUPnP;
             }
+            else if (strType == "minversion")
+            {
+                int nMinVersion = 0;
+                ssValue >> nMinVersion;
+                if (nMinVersion > VERSION)
+                    return DB_TOO_NEW;
+            }
         }
         pcursor->close();
     }
 
     BOOST_FOREACH(uint256 hash, vWalletUpgrade)
-        WriteTx(hash, mapWallet[hash]);
+        WriteTx(hash, pwallet->mapWallet[hash]);
 
     printf("nFileVersion = %d\n", nFileVersion);
     printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
     printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
-    printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
     printf("fMinimizeToTray = %d\n", fMinimizeToTray);
     printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
     printf("fUseProxy = %d\n", fUseProxy);
@@ -825,39 +870,12 @@ bool CWalletDB::LoadWallet()
     }
 
 
-    return true;
-}
-
-bool LoadWallet(bool& fFirstRunRet)
-{
-    fFirstRunRet = false;
-    if (!CWalletDB("cr+").LoadWallet())
-        return false;
-    fFirstRunRet = vchDefaultKey.empty();
-
-    if (mapKeys.count(vchDefaultKey))
-    {
-        // Set keyUser
-        keyUser.SetPubKey(vchDefaultKey);
-        keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
-    }
-    else
-    {
-        // Create new keyUser and set as default key
-        RandAddSeedPerfmon();
-
-        CWalletDB walletdb;
-        vchDefaultKey = GetKeyFromKeyPool();
-        walletdb.WriteDefaultKey(vchDefaultKey);
-        walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
-    }
-
-    CreateThread(ThreadFlushWalletDB, NULL);
-    return true;
+    return DB_LOAD_OK;
 }
 
 void ThreadFlushWalletDB(void* parg)
 {
+    const string& strFile = ((const string*)parg)[0];
     static bool fOneThread;
     if (fOneThread)
         return;
@@ -893,7 +911,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())
                     {
@@ -916,26 +933,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
@@ -943,83 +961,10 @@ void BackupWallet(const string& strDest)
 #endif
                 printf("copied wallet.dat to %s\n", pathDest.string().c_str());
 
-                return;
+                return true;
             }
         }
         Sleep(100);
     }
-}
-
-
-void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
-{
-    nIndex = -1;
-    keypool.vchPubKey.clear();
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_setKeyPool)
-    {
-        // Top up key pool
-        int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
-        while (setKeyPool.size() < nTargetSize+1)
-        {
-            int64 nEnd = 1;
-            if (!setKeyPool.empty())
-                nEnd = *(--setKeyPool.end()) + 1;
-            if (!Write(make_pair(string("pool"), 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());
-        }
-
-        // Get the oldest key
-        assert(!setKeyPool.empty());
-        nIndex = *(setKeyPool.begin());
-        setKeyPool.erase(setKeyPool.begin());
-        if (!Read(make_pair(string("pool"), nIndex), keypool))
-            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
-        if (!mapKeys.count(keypool.vchPubKey))
-            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
-        assert(!keypool.vchPubKey.empty());
-        printf("keypool reserve %"PRI64d"\n", nIndex);
-    }
-}
-
-void CWalletDB::KeepKey(int64 nIndex)
-{
-    // Remove from key pool
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        Erase(make_pair(string("pool"), nIndex));
-    }
-    printf("keypool keep %"PRI64d"\n", nIndex);
-}
-
-void CWalletDB::ReturnKey(int64 nIndex)
-{
-    // Return to key pool
-    CRITICAL_BLOCK(cs_setKeyPool)
-        setKeyPool.insert(nIndex);
-    printf("keypool return %"PRI64d"\n", nIndex);
-}
-
-vector<unsigned char> GetKeyFromKeyPool()
-{
-    CWalletDB walletdb;
-    int64 nIndex = 0;
-    CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.KeepKey(nIndex);
-    return keypool.vchPubKey;
-}
-
-int64 GetOldestKeyPoolTime()
-{
-    CWalletDB walletdb;
-    int64 nIndex = 0;
-    CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.ReturnKey(nIndex);
-    return keypool.nTime;
+    return false;
 }