Use CBigNum for temporary variables to prevent overflow. Which is unlikely to happen...
[novacoin.git] / src / walletdb.cpp
index bc9437b..efb5955 100644 (file)
 
 #include <boost/version.hpp>
 #include <boost/filesystem.hpp>
-#include <boost/algorithm/string.hpp>
-
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/variant/get.hpp>
-#include <boost/algorithm/string.hpp>
 
 using namespace std;
-using namespace boost;
-
 
 static uint64_t nAccountingEntryNumber = 0;
 extern bool fWalletUnlockMintOnly;
 
 //
+//CKeyMetadata
+//
+
+CKeyMetadata::CKeyMetadata()
+{
+    SetNull();
+}
+
+CKeyMetadata::CKeyMetadata(int64_t nCreateTime_)
+{
+    nVersion = CKeyMetadata::CURRENT_VERSION;
+    nCreateTime = nCreateTime_;
+}
+
+void CKeyMetadata::SetNull()
+{
+    nVersion = CKeyMetadata::CURRENT_VERSION;
+    nCreateTime = 0;
+}
+
+//
 // CWalletDB
 //
 
+CWalletDB::CWalletDB(string strFilename, const char* pszMode) : CDB(strFilename.c_str(), pszMode) {}
+
 bool CWalletDB::WriteName(const string& strAddress, const string& strName)
 {
     nWalletDBUpdated++;
@@ -44,6 +59,159 @@ bool CWalletDB::EraseName(const string& strAddress)
     return Erase(make_pair(string("name"), strAddress));
 }
 
+bool CWalletDB::WriteTx(uint256 hash, const CWalletTx& wtx)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("tx"), hash), wtx);
+}
+
+bool CWalletDB::EraseTx(uint256 hash)
+{
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("tx"), hash));
+}
+
+bool CWalletDB::WriteKey(const CPubKey& key, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta)
+{
+    nWalletDBUpdated++;
+    if(!Write(make_pair(string("keymeta"), key), keyMeta))
+        return false;
+
+    if(!Write(make_pair(string("key"), key), vchPrivKey, false))
+        return false;
+
+    return true;
+}
+
+bool CWalletDB::WriteMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH, const CKeyMetadata &keyMeta)
+{
+    nWalletDBUpdated++;
+    if(!Write(make_pair(string("malmeta"), keyView.ToString()), keyMeta))
+        return false;
+
+    if(!Write(make_pair(string("malpair"), keyView.ToString()), vchSecretH, false))
+        return false;
+
+    return true;
+}
+
+bool CWalletDB::WriteCryptedMalleableKey(const CMalleableKeyView& keyView, const vector<unsigned char>& vchCryptedSecretH, const CKeyMetadata &keyMeta)
+{
+    nWalletDBUpdated++;
+    if(!Write(make_pair(string("malmeta"), keyView.ToString()), keyMeta))
+        return false;
+
+    if(!Write(make_pair(string("malcpair"), keyView.ToString()), vchCryptedSecretH, false))
+        return false;
+
+    Erase(make_pair(string("malpair"), keyView.ToString()));
+
+    return true;
+}
+
+bool CWalletDB::WriteCryptedKey(const CPubKey& key, const vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
+{
+    nWalletDBUpdated++;
+    bool fEraseUnencryptedKey = true;
+
+    if(!Write(make_pair(string("keymeta"), key), keyMeta))
+        return false;
+
+    if (!Write(make_pair(string("ckey"), key), vchCryptedSecret, false))
+        return false;
+    if (fEraseUnencryptedKey)
+    {
+        Erase(make_pair(string("key"), key));
+        Erase(make_pair(string("wkey"), key));
+    }
+    return true;
+}
+
+bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("mkey"), nID), kMasterKey, true);
+}
+
+bool CWalletDB::EraseMasterKey(unsigned int nID)
+{
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("mkey"), nID));
+}
+
+bool CWalletDB::EraseCryptedKey(const CPubKey& key)
+{
+    return Erase(make_pair(string("ckey"), key));
+}
+
+bool CWalletDB::EraseCryptedMalleableKey(const CMalleableKeyView& keyView)
+{
+    return Erase(make_pair(string("malcpair"), keyView.ToString()));
+}
+
+bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("cscript"), hash), redeemScript, false);
+}
+
+bool CWalletDB::WriteWatchOnly(const CScript &dest)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("watchs"), dest), '1');
+}
+
+bool CWalletDB::EraseWatchOnly(const CScript &dest)
+{
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("watchs"), dest));
+}
+
+bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
+{
+    nWalletDBUpdated++;
+    return Write(string("bestblock"), locator);
+}
+
+bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
+{
+    return Read(string("bestblock"), locator);
+}
+
+bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
+{
+    nWalletDBUpdated++;
+    return Write(string("orderposnext"), nOrderPosNext);
+}
+
+bool CWalletDB::WriteDefaultKey(const CPubKey& key)
+{
+    nWalletDBUpdated++;
+    return Write(string("defaultkey"), key);
+}
+
+bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
+{
+    return Read(make_pair(string("pool"), nPool), keypool);
+}
+
+bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("pool"), nPool), keypool);
+}
+
+bool CWalletDB::ErasePool(int64_t nPool)
+{
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("pool"), nPool));
+}
+
+bool CWalletDB::WriteMinVersion(int nVersion)
+{
+    return Write(string("minversion"), nVersion);
+}
+
 bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
 {
     account.SetNull();
@@ -57,7 +225,7 @@ bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
 
 bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
 {
-    return Write(std::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry);
+    return Write(make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry);
 }
 
 bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
@@ -90,7 +258,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
         // Read next record
         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
         if (fFlags == DB_SET_RANGE)
-            ssKey << std::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0));
+            ssKey << make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0));
         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
         int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
         fFlags = DB_NEXT;
@@ -147,7 +315,7 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
 
     int64_t& nOrderPosNext = pwallet->nOrderPosNext;
     nOrderPosNext = 0;
-    std::vector<int64_t> nOrderPosOffsets;
+    vector<int64_t> nOrderPosOffsets;
     for (auto it = txByTime.begin(); it != txByTime.end(); ++it)
     {
         CWalletTx *const pwtx = (*it).second.first;
@@ -173,7 +341,7 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
                     ++nOrderPosOff;
             }
             nOrderPos += nOrderPosOff;
-            nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1);
+            nOrderPosNext = max(nOrderPosNext, nOrderPos + 1);
 
             if (!nOrderPosOff)
                 continue;
@@ -321,7 +489,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
         {
             string strKeyView;
 
-            std::vector<unsigned char> vchCryptedSecret;
+            vector<unsigned char> vchCryptedSecret;
             ssKey >> strKeyView;
             ssValue >> vchCryptedSecret;
 
@@ -713,7 +881,7 @@ void ThreadFlushWalletDB(void* parg)
             {
                 // Don't do this if any databases are in use
                 int nRefCount = 0;
-                map<string, int>::iterator mi = bitdb.mapFileUseCount.begin();
+                auto mi = bitdb.mapFileUseCount.begin();
                 while (mi != bitdb.mapFileUseCount.end())
                 {
                     nRefCount += (*mi).second;
@@ -722,7 +890,7 @@ void ThreadFlushWalletDB(void* parg)
 
                 if (nRefCount == 0 && !fShutdown)
                 {
-                    map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
+                    auto mi = bitdb.mapFileUseCount.find(strFile);
                     if (mi != bitdb.mapFileUseCount.end())
                     {
                         printf("Flushing wallet.dat\n");
@@ -758,20 +926,20 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
                 bitdb.mapFileUseCount.erase(wallet.strWalletFile);
 
                 // Copy wallet.dat
-                filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
-                filesystem::path pathDest(strDest);
-                if (filesystem::is_directory(pathDest))
+                boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
+                boost::filesystem::path pathDest(strDest);
+                if (boost::filesystem::is_directory(pathDest))
                     pathDest /= wallet.strWalletFile;
 
                 try {
 #if BOOST_VERSION >= 104000
-                    filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
+                    boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
 #else
-                    filesystem::copy_file(pathSrc, pathDest);
+                    boost::filesystem::copy_file(pathSrc, pathDest);
 #endif
                     printf("copied wallet.dat to %s\n", pathDest.string().c_str());
                     return true;
-                } catch(const filesystem::filesystem_error &e) {
+                } catch(const boost::filesystem::filesystem_error &e) {
                     printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
                     return false;
                 }
@@ -787,19 +955,19 @@ bool DumpWallet(CWallet* pwallet, const string& strDest)
     if (!pwallet->fFileBacked)
         return false;
 
-    std::map<CBitcoinAddress, int64_t> mapAddresses;
-    std::set<CKeyID> setKeyPool;
+    map<CBitcoinAddress, int64_t> mapAddresses;
+    set<CKeyID> setKeyPool;
 
     pwallet->GetAddresses(mapAddresses);
     pwallet->GetAllReserveKeys(setKeyPool);
 
     // sort time/key pairs
-    std::vector<std::pair<int64_t, CBitcoinAddress> > vAddresses;
+    vector<pair<int64_t, CBitcoinAddress> > vAddresses;
     for (auto it = mapAddresses.begin(); it != mapAddresses.end(); it++) {
-        vAddresses.push_back(std::make_pair(it->second, it->first));
+        vAddresses.push_back({ it->second, it->first });
     }
     mapAddresses.clear();
-    std::sort(vAddresses.begin(), vAddresses.end());
+    sort(vAddresses.begin(), vAddresses.end());
 
     // open outputfile as a stream
     ofstream file;
@@ -814,10 +982,10 @@ bool DumpWallet(CWallet* pwallet, const string& strDest)
     file << strprintf("#   mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
     file << "\n";
 
-    for (auto it = vAddresses.begin(); it != vAddresses.end(); it++) {
-        const CBitcoinAddress &addr = it->second;
-        std::string strTime = EncodeDumpTime(it->first);
-        std::string strAddr = addr.ToString();
+    for (const auto& addrItem : vAddresses) {
+        const auto &addr = addrItem.second;
+        const auto strTime = EncodeDumpTime(addrItem.first);
+        const auto strAddr = addr.ToString();
 
         if (addr.IsPair()) {
             // Pubkey pair address
@@ -841,7 +1009,7 @@ bool DumpWallet(CWallet* pwallet, const string& strDest)
             CKey key;
             if (!pwallet->GetKey(keyid, key))
                 continue;
-            CSecret secret = key.GetSecret(IsCompressed);
+            auto secret = key.GetSecret(IsCompressed);
             file << CBitcoinSecret(secret, IsCompressed).ToString();
             if (pwallet->mapAddressBook.count(addr))
                 file << strprintf(" %s label=%s # addr=%s\n", strTime.c_str(), EncodeDumpString(pwallet->mapAddressBook[addr]).c_str(), strAddr.c_str());
@@ -876,19 +1044,19 @@ bool ImportWallet(CWallet *pwallet, const string& strLocation)
 
    // read through input file checking and importing keys into wallet.
    while (file.good()) {
-       std::string line;
-       std::getline(file, line);
+       string line;
+       getline(file, line);
        if (line.empty() || line[0] == '#')
            continue; // Skip comments and empty lines
 
-       std::vector<std::string> vstr;
+       vector<string> vstr;
        istringstream iss(line);
        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(vstr));
        if (vstr.size() < 2)
            continue;
 
        int64_t nTime = DecodeDumpTime(vstr[1]);
-       std::string strLabel;
+       string strLabel;
        bool fLabel = true;
        for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
            if (vstr[nStr].compare(0,1, "#") == 0)
@@ -910,9 +1078,9 @@ bool ImportWallet(CWallet *pwallet, const string& strLocation)
 
            bool fCompressed;
            CKey key;
-           CSecret secret = vchSecret.GetSecret(fCompressed);
+           auto secret = vchSecret.GetSecret(fCompressed);
            key.SetSecret(secret, fCompressed);
-           CKeyID keyid = key.GetPubKey().GetID();
+           auto keyid = key.GetPubKey().GetID();
            addr = CBitcoinAddress(keyid);
 
            if (pwallet->HaveKey(keyid)) {
@@ -931,7 +1099,7 @@ bool ImportWallet(CWallet *pwallet, const string& strLocation)
            CMalleableKey mKey;
            if (!mKey.SetString(vstr[0]))
                continue;
-           CMalleablePubKey mPubKey = mKey.GetMalleablePubKey();
+           auto mPubKey = mKey.GetMalleablePubKey();
            addr = CBitcoinAddress(mPubKey);
 
            if (pwallet->CheckOwnership(mPubKey)) {
@@ -950,7 +1118,7 @@ bool ImportWallet(CWallet *pwallet, const string& strLocation)
        if (fLabel)
            pwallet->SetAddressBookName(addr, strLabel);
 
-       nTimeBegin = std::min(nTimeBegin, nTime);
+       nTimeBegin = min(nTimeBegin, nTime);
    }
    file.close();
 
@@ -970,7 +1138,7 @@ bool ImportWallet(CWallet *pwallet, const string& strLocation)
 //
 // Try to (very carefully!) recover wallet.dat if there is a problem.
 //
-bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
+bool CWalletDB::Recover(CDBEnv& dbenv, string filename, bool fOnlyKeys)
 {
     // Recovery procedure:
     // move wallet.dat to wallet.timestamp.bak
@@ -980,7 +1148,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
     // Set -rescan so any missing transactions will be
     // found.
     int64_t now = GetTime();
-    std::string newFilename = strprintf("wallet.%" PRId64 ".bak", now);
+    string newFilename = strprintf("wallet.%" PRId64 ".bak", now);
 
     int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL,
                                       newFilename.c_str(), DB_AUTO_COMMIT);
@@ -992,7 +1160,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
         return false;
     }
 
-    std::vector<CDBEnv::KeyValPair> salvagedData;
+    vector<CDBEnv::KeyValPair> salvagedData;
     bool allOK = dbenv.Salvage(newFilename, true, salvagedData);
     if (salvagedData.empty())
     {
@@ -1002,7 +1170,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
     printf("Salvage(aggressive) found %" PRIszu " records\n", salvagedData.size());
 
     bool fSuccess = allOK;
-    Db* pdbCopy = new Db(&dbenv.dbenv, 0);
+    unique_ptr<Db> pdbCopy(new Db(&dbenv.dbenv, 0));
     int ret = pdbCopy->open(NULL,                 // Txn pointer
                             filename.c_str(),   // Filename
                             "main",    // Logical db name
@@ -1043,12 +1211,11 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
     }
     ptxn->commit(0);
     pdbCopy->close(0);
-    delete pdbCopy;
 
     return fSuccess;
 }
 
-bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename)
+bool CWalletDB::Recover(CDBEnv& dbenv, string filename)
 {
     return CWalletDB::Recover(dbenv, filename, false);
 }