Move importwallet and dumpwallet implementations to walletdb.cpp;
authorCryptoManiac <balthazar@yandex.ru>
Mon, 16 Jun 2014 00:07:48 +0000 (04:07 +0400)
committerCryptoManiac <balthazar@yandex.ru>
Thu, 10 Jul 2014 17:44:13 +0000 (21:44 +0400)
Move timestamps encoding and decoding functions to util.cpp.

src/db.h
src/rpcdump.cpp
src/util.cpp
src/util.h
src/walletdb.cpp

index 9a8af31..750d6b0 100644 (file)
--- a/src/db.h
+++ b/src/db.h
@@ -28,7 +28,8 @@ extern unsigned int nWalletDBUpdated;
 
 void ThreadFlushWalletDB(void* parg);
 bool BackupWallet(const CWallet& wallet, const std::string& strDest);
-
+bool DumpWallet(CWallet* pwallet, const std::string& strDest);
+bool ImportWallet(CWallet* pwallet, const std::string& strLocation);
 
 class CDBEnv
 {
index b0284f9..1e31e73 100644 (file)
@@ -2,19 +2,11 @@
 // Distributed under the MIT/X11 software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
-#include <iostream>
-#include <fstream>
-
 #include "init.h" // for pwalletMain
 #include "bitcoinrpc.h"
 #include "ui_interface.h"
 #include "base58.h"
 
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/variant/get.hpp>
-#include <boost/algorithm/string.hpp>
-
 #define printf OutputDebugStringF
 
 using namespace json_spirit;
@@ -22,72 +14,6 @@ using namespace std;
 
 void EnsureWalletIsUnlocked();
 
-namespace bt = boost::posix_time;
-
-// Extended DecodeDumpTime implementation, see this page for details:
-// http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
-const std::locale formats[] = {
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
-};
-
-const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
-
-std::time_t pt_to_time_t(const bt::ptime& pt)
-{
-    bt::ptime timet_start(boost::gregorian::date(1970,1,1));
-    bt::time_duration diff = pt - timet_start;
-    return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
-}
-
-int64 DecodeDumpTime(const std::string& s)
-{
-    bt::ptime pt;
-
-    for(size_t i=0; i<formats_n; ++i)
-    {
-        std::istringstream is(s);
-        is.imbue(formats[i]);
-        is >> pt;
-        if(pt != bt::ptime()) break;
-    }
-
-    return pt_to_time_t(pt);
-}
-
-std::string static EncodeDumpTime(int64 nTime) {
-    return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
-}
-
-std::string static EncodeDumpString(const std::string &str) {
-    std::stringstream ret;
-    BOOST_FOREACH(unsigned char c, str) {
-        if (c <= 32 || c >= 128 || c == '%') {
-            ret << '%' << HexStr(&c, &c + 1);
-        } else {
-            ret << c;
-        }
-    }
-    return ret.str();
-}
-
-std::string DecodeDumpString(const std::string &str) {
-    std::stringstream ret;
-    for (unsigned int pos = 0; pos < str.length(); pos++) {
-        unsigned char c = str[pos];
-        if (c == '%' && pos+2 < str.length()) {
-            c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | 
-                ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
-            pos += 2;
-        }
-        ret << c;
-    }
-    return ret.str();
-}
-
 class CTxDump
 {
 public:
@@ -150,86 +76,17 @@ Value importwallet(const Array& params, bool fHelp)
     if (fHelp || params.size() != 1)
         throw runtime_error(
             "importwallet <filename>\n"
-            "Imports keys from a wallet dump file (see dumpwallet).");
+            "Imports keys from a wallet dump file (see dumpwallet)."
+            + HelpRequiringPassphrase());
 
     EnsureWalletIsUnlocked();
 
-    ifstream file;
-    file.open(params[0].get_str().c_str());
-    if (!file.is_open())
-        throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
-
-    int64 nTimeBegin = pindexBest->nTime;
-
-    bool fGood = true;
-
-    while (file.good()) {
-        std::string line;
-        std::getline(file, line);
-        if (line.empty() || line[0] == '#')
-            continue;
-
-        std::vector<std::string> vstr;
-        boost::split(vstr, line, boost::is_any_of(" "));
-        if (vstr.size() < 2)
-            continue;
-        CBitcoinSecret vchSecret;
-        if (!vchSecret.SetString(vstr[0]))
-            continue;
-
-        bool fCompressed;
-        CKey key;
-        CSecret secret = vchSecret.GetSecret(fCompressed);
-        key.SetSecret(secret, fCompressed);
-        CKeyID keyid = key.GetPubKey().GetID();
-
-        if (pwalletMain->HaveKey(keyid)) {
-            printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
-            continue;
-        }
-        int64 nTime = DecodeDumpTime(vstr[1]);
-        std::string strLabel;
-        bool fLabel = true;
-        for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
-            if (boost::algorithm::starts_with(vstr[nStr], "#"))
-                break;
-            if (vstr[nStr] == "change=1")
-                fLabel = false;
-            if (vstr[nStr] == "reserve=1")
-                fLabel = false;
-            if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
-                strLabel = DecodeDumpString(vstr[nStr].substr(6));
-                fLabel = true;
-            }
-        }
-        printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
-        if (!pwalletMain->AddKey(key)) {
-            fGood = false;
-            continue;
-        }
-        pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
-        if (fLabel)
-            pwalletMain->SetAddressBookName(keyid, strLabel);
-        nTimeBegin = std::min(nTimeBegin, nTime);
-    }
-    file.close();
-
-    CBlockIndex *pindex = pindexBest;
-    while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
-        pindex = pindex->pprev;
-
-    printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
-    pwalletMain->ScanForWalletTransactions(pindex);
-    pwalletMain->ReacceptWalletTransactions();
-    pwalletMain->MarkDirty();
-
-    if (!fGood)
-        throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
+    if(!ImportWallet(pwalletMain, params[0].get_str().c_str()))
+       throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
 
     return Value::null;
 }
 
-
 Value dumpprivkey(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 1)
@@ -260,59 +117,13 @@ Value dumpwallet(const Array& params, bool fHelp)
     if (fHelp || params.size() != 1)
         throw runtime_error(
             "dumpwallet <filename>\n"
-            "Dumps all wallet keys in a human-readable format.");
+            "Dumps all wallet keys in a human-readable format."
+            + HelpRequiringPassphrase());
 
     EnsureWalletIsUnlocked();
 
-    ofstream file;
-    file.open(params[0].get_str().c_str());
-    if (!file.is_open())
-        throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
-
-    std::map<CKeyID, int64> mapKeyBirth;
-
-    std::set<CKeyID> setKeyPool;
-
-    pwalletMain->GetKeyBirthTimes(mapKeyBirth);
+    if(!DumpWallet(pwalletMain, params[0].get_str().c_str() ))
+      throw JSONRPCError(RPC_WALLET_ERROR, "Error dumping wallet keys to file");
 
-    pwalletMain->GetAllReserveKeys(setKeyPool);
-
-    // sort time/key pairs
-    std::vector<std::pair<int64, CKeyID> > vKeyBirth;
-    for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
-        vKeyBirth.push_back(std::make_pair(it->second, it->first));
-    }
-    mapKeyBirth.clear();
-    std::sort(vKeyBirth.begin(), vKeyBirth.end());
-
-    // produce output
-    file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
-    file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
-    file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
-    file << strprintf("#   mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
-    file << "\n";
-    for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
-        const CKeyID &keyid = it->second;
-        std::string strTime = EncodeDumpTime(it->first);
-        std::string strAddr = CBitcoinAddress(keyid).ToString();
-        bool IsCompressed;
-
-        CKey key;
-        if (pwalletMain->GetKey(keyid, key)) {
-            if (pwalletMain->mapAddressBook.count(keyid)) {
-                CSecret secret = key.GetSecret(IsCompressed);
-                file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), EncodeDumpString(pwalletMain->mapAddressBook[keyid]).c_str(), strAddr.c_str());
-            } else if (setKeyPool.count(keyid)) {
-                CSecret secret = key.GetSecret(IsCompressed);
-                file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str());
-            } else {
-                CSecret secret = key.GetSecret(IsCompressed);
-                file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str());
-            }
-        }
-    }
-    file << "\n";
-    file << "# End of dump\n";
-    file.close();
     return Value::null;
 }
index a527cb2..5422d0b 100644 (file)
@@ -24,6 +24,8 @@ namespace boost {
 #include <boost/program_options/parsers.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/foreach.hpp>
 #include <boost/thread.hpp>
 #include <openssl/crypto.h>
@@ -61,6 +63,7 @@ namespace boost {
 
 
 using namespace std;
+namespace bt = boost::posix_time;
 
 map<string, string> mapArgs;
 map<string, vector<string> > mapMultiArgs;
@@ -80,6 +83,25 @@ bool fLogTimestamps = false;
 CMedianFilter<int64> vTimeOffsets(200,0);
 bool fReopenDebugLog = false;
 
+// Extended DecodeDumpTime implementation, see this page for details:
+// http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
+const std::locale formats[] = {
+    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
+    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
+    std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
+    std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
+    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
+};
+
+const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
+
+std::time_t pt_to_time_t(const bt::ptime& pt)
+{
+    bt::ptime timet_start(boost::gregorian::date(1970,1,1));
+    bt::time_duration diff = pt - timet_start;
+    return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
+}
+
 // Init OpenSSL library multithreading support
 static CCriticalSection** ppmutexOpenSSL;
 void locking_callback(int mode, int i, const char* file, int line)
@@ -918,6 +940,51 @@ string DecodeBase32(const string& str)
 }
 
 
+int64 DecodeDumpTime(const std::string& s)
+{
+    bt::ptime pt;
+
+    for(size_t i=0; i<formats_n; ++i)
+    {
+        std::istringstream is(s);
+        is.imbue(formats[i]);
+        is >> pt;
+        if(pt != bt::ptime()) break;
+    }
+
+    return pt_to_time_t(pt);
+}
+
+std::string EncodeDumpTime(int64 nTime) {
+    return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
+}
+
+std::string EncodeDumpString(const std::string &str) {
+    std::stringstream ret;
+    BOOST_FOREACH(unsigned char c, str) {
+        if (c <= 32 || c >= 128 || c == '%') {
+            ret << '%' << HexStr(&c, &c + 1);
+        } else {
+            ret << c;
+        }
+    }
+    return ret.str();
+}
+
+std::string DecodeDumpString(const std::string &str) {
+    std::stringstream ret;
+    for (unsigned int pos = 0; pos < str.length(); pos++) {
+        unsigned char c = str[pos];
+        if (c == '%' && pos+2 < str.length()) {
+            c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | 
+                ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
+            pos += 2;
+        }
+        ret << c;
+    }
+    return ret.str();
+}
+
 bool WildcardMatch(const char* psz, const char* mask)
 {
     while (true)
index 1d182be..0f08df8 100644 (file)
@@ -204,6 +204,10 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
 std::string DecodeBase32(const std::string& str);
 std::string EncodeBase32(const unsigned char* pch, size_t len);
 std::string EncodeBase32(const std::string& str);
+std::string EncodeDumpTime(int64 nTime);
+int64 DecodeDumpTime(const std::string& s);
+std::string EncodeDumpString(const std::string &str);
+std::string DecodeDumpString(const std::string &str);
 void ParseParameters(int argc, const char*const argv[]);
 bool WildcardMatch(const char* psz, const char* mask);
 bool WildcardMatch(const std::string& str, const std::string& mask);
index 087ac9b..e23b291 100644 (file)
@@ -5,8 +5,18 @@
 
 #include "walletdb.h"
 #include "wallet.h"
+
+#include <iostream>
+#include <fstream>
+
 #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;
@@ -632,6 +642,166 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
     return false;
 }
 
+bool DumpWallet(CWallet* pwallet, const string& strDest)
+{
+
+  if (!pwallet->fFileBacked)
+      return false;
+  while (!fShutdown)
+  {
+      // Populate maps
+      std::map<CKeyID, int64> mapKeyBirth;
+      std::set<CKeyID> setKeyPool;
+      pwallet->GetKeyBirthTimes(mapKeyBirth);
+      pwallet->GetAllReserveKeys(setKeyPool);
+
+      // sort time/key pairs
+      std::vector<std::pair<int64, CKeyID> > vKeyBirth;
+      for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
+          vKeyBirth.push_back(std::make_pair(it->second, it->first));
+      }
+      mapKeyBirth.clear();
+      std::sort(vKeyBirth.begin(), vKeyBirth.end());
+
+      // open outputfile as a stream
+      ofstream file;
+      file.open(strDest.c_str());
+      if (!file.is_open())
+         return false;
+
+      // produce output
+      file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
+      file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
+      file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
+      file << strprintf("#   mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+      file << "\n";
+      for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
+          const CKeyID &keyid = it->second;
+          std::string strTime = EncodeDumpTime(it->first);
+          std::string strAddr = CBitcoinAddress(keyid).ToString();
+          bool IsCompressed;
+
+          CKey key;
+          if (pwallet->GetKey(keyid, key)) {
+              if (pwallet->mapAddressBook.count(keyid)) {
+                  CSecret secret = key.GetSecret(IsCompressed);
+                  file << strprintf("%s %s label=%s # addr=%s\n",
+                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                    strTime.c_str(),
+                                    EncodeDumpString(pwallet->mapAddressBook[keyid]).c_str(),
+                                    strAddr.c_str());
+              } else if (setKeyPool.count(keyid)) {
+                  CSecret secret = key.GetSecret(IsCompressed);
+                  file << strprintf("%s %s reserve=1 # addr=%s\n",
+                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                    strTime.c_str(),
+                                    strAddr.c_str());
+              } else {
+                  CSecret secret = key.GetSecret(IsCompressed);
+                  file << strprintf("%s %s change=1 # addr=%s\n",
+                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                    strTime.c_str(),
+                                    strAddr.c_str());
+              }
+          }
+      }
+      file << "\n";
+      file << "# End of dump\n";
+      file.close();
+      return true;
+     }
+   return false;
+}
+
+
+bool ImportWallet(CWallet *pwallet, const string& strLocation)
+{
+
+   if (!pwallet->fFileBacked)
+       return false;
+   while (!fShutdown)
+   {
+      // open inputfile as stream
+      ifstream file;
+      file.open(strLocation.c_str());
+      if (!file.is_open())
+          return false;
+
+      int64 nTimeBegin = pindexBest->nTime;
+
+      bool fGood = true;
+
+      // read through input file checking and importing keys into wallet.
+      while (file.good()) {
+          std::string line;
+          std::getline(file, line);
+          if (line.empty() || line[0] == '#')
+              continue;
+
+          std::vector<std::string> vstr;
+          boost::split(vstr, line, boost::is_any_of(" "));
+          if (vstr.size() < 2)
+              continue;
+          CBitcoinSecret vchSecret;
+          if (!vchSecret.SetString(vstr[0]))
+              continue;
+
+          bool fCompressed;
+          CKey key;
+          CSecret secret = vchSecret.GetSecret(fCompressed);
+          key.SetSecret(secret, fCompressed);
+          CKeyID keyid = key.GetPubKey().GetID();
+
+          if (pwallet->HaveKey(keyid)) {
+              printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
+             continue;
+          }
+          int64 nTime = DecodeDumpTime(vstr[1]);
+          std::string strLabel;
+          bool fLabel = true;
+          for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
+              if (boost::algorithm::starts_with(vstr[nStr], "#"))
+                  break;
+              if (vstr[nStr] == "change=1")
+                  fLabel = false;
+              if (vstr[nStr] == "reserve=1")
+                  fLabel = false;
+              if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
+                  strLabel = DecodeDumpString(vstr[nStr].substr(6));
+                  fLabel = true;
+              }
+          }
+          printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
+          if (!pwallet->AddKey(key)) {
+              fGood = false;
+              continue;
+          }
+          pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
+          if (fLabel)
+              pwallet->SetAddressBookName(keyid, strLabel);
+          nTimeBegin = std::min(nTimeBegin, nTime);
+      }
+      file.close();
+
+      // rescan block chain looking for coins from new keys
+      CBlockIndex *pindex = pindexBest;
+      while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
+          pindex = pindex->pprev;
+
+      printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
+      pwallet->ScanForWalletTransactions(pindex);
+      pwallet->ReacceptWalletTransactions();
+      pwallet->MarkDirty();
+
+      return fGood;
+
+  }
+
+  return false;
+
+}
+
+
 //
 // Try to (very carefully!) recover wallet.dat if there is a problem.
 //