LCOV - code coverage report
Current view: top level - src/wallet - rpcdump.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 161 266 60.5 %
Date: 2015-10-12 22:39:14 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "base58.h"
       6             : #include "chain.h"
       7             : #include "rpcserver.h"
       8             : #include "init.h"
       9             : #include "main.h"
      10             : #include "script/script.h"
      11             : #include "script/standard.h"
      12             : #include "sync.h"
      13             : #include "util.h"
      14             : #include "utiltime.h"
      15             : #include "wallet.h"
      16             : 
      17             : #include <fstream>
      18             : #include <stdint.h>
      19             : 
      20             : #include <boost/algorithm/string.hpp>
      21             : #include <boost/date_time/posix_time/posix_time.hpp>
      22             : 
      23             : #include <univalue.h>
      24             : 
      25             : #include <boost/foreach.hpp>
      26             : 
      27             : using namespace std;
      28             : 
      29             : void EnsureWalletIsUnlocked();
      30             : bool EnsureWalletIsAvailable(bool avoidException);
      31             : 
      32             : std::string static EncodeDumpTime(int64_t nTime) {
      33         343 :     return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
      34             : }
      35             : 
      36         337 : int64_t static DecodeDumpTime(const std::string &str) {
      37         337 :     static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
      38           3 :     static const std::locale loc(std::locale::classic(),
      39         346 :         new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
      40         337 :     std::istringstream iss(str);
      41         337 :     iss.imbue(loc);
      42             :     boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
      43         337 :     iss >> ptime;
      44         337 :     if (ptime.is_not_a_date_time())
      45             :         return 0;
      46         337 :     return (ptime - epoch).total_seconds();
      47             : }
      48             : 
      49          18 : std::string static EncodeDumpString(const std::string &str) {
      50          18 :     std::stringstream ret;
      51          90 :     BOOST_FOREACH(unsigned char c, str) {
      52           0 :         if (c <= 32 || c >= 128 || c == '%') {
      53           0 :             ret << '%' << HexStr(&c, &c + 1);
      54             :         } else {
      55           0 :             ret << c;
      56             :         }
      57             :     }
      58          18 :     return ret.str();
      59             : }
      60             : 
      61          18 : std::string DecodeDumpString(const std::string &str) {
      62          18 :     std::stringstream ret;
      63          18 :     for (unsigned int pos = 0; pos < str.length(); pos++) {
      64           0 :         unsigned char c = str[pos];
      65           0 :         if (c == '%' && pos+2 < str.length()) {
      66           0 :             c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | 
      67           0 :                 ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
      68           0 :             pos += 2;
      69             :         }
      70           0 :         ret << c;
      71             :     }
      72          18 :     return ret.str();
      73             : }
      74             : 
      75           0 : UniValue importprivkey(const UniValue& params, bool fHelp)
      76             : {
      77           0 :     if (!EnsureWalletIsAvailable(fHelp))
      78           0 :         return NullUniValue;
      79             :     
      80           0 :     if (fHelp || params.size() < 1 || params.size() > 3)
      81             :         throw runtime_error(
      82             :             "importprivkey \"bitcoinprivkey\" ( \"label\" rescan )\n"
      83             :             "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
      84             :             "\nArguments:\n"
      85             :             "1. \"bitcoinprivkey\"   (string, required) The private key (see dumpprivkey)\n"
      86             :             "2. \"label\"            (string, optional, default=\"\") An optional label\n"
      87             :             "3. rescan               (boolean, optional, default=true) Rescan the wallet for transactions\n"
      88             :             "\nNote: This call can take minutes to complete if rescan is true.\n"
      89             :             "\nExamples:\n"
      90             :             "\nDump a private key\n"
      91           0 :             + HelpExampleCli("dumpprivkey", "\"myaddress\"") +
      92             :             "\nImport the private key with rescan\n"
      93           0 :             + HelpExampleCli("importprivkey", "\"mykey\"") +
      94             :             "\nImport using a label and without rescan\n"
      95           0 :             + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
      96             :             "\nAs a JSON-RPC call\n"
      97           0 :             + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
      98           0 :         );
      99             : 
     100             : 
     101           0 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     102             : 
     103           0 :     EnsureWalletIsUnlocked();
     104             : 
     105           0 :     string strSecret = params[0].get_str();
     106           0 :     string strLabel = "";
     107           0 :     if (params.size() > 1)
     108           0 :         strLabel = params[1].get_str();
     109             : 
     110             :     // Whether to perform rescan after import
     111           0 :     bool fRescan = true;
     112           0 :     if (params.size() > 2)
     113           0 :         fRescan = params[2].get_bool();
     114             : 
     115           0 :     if (fRescan && fPruneMode)
     116           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
     117             : 
     118             :     CBitcoinSecret vchSecret;
     119           0 :     bool fGood = vchSecret.SetString(strSecret);
     120             : 
     121           0 :     if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
     122             : 
     123           0 :     CKey key = vchSecret.GetKey();
     124           0 :     if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
     125             : 
     126           0 :     CPubKey pubkey = key.GetPubKey();
     127           0 :     assert(key.VerifyPubKey(pubkey));
     128           0 :     CKeyID vchAddress = pubkey.GetID();
     129             :     {
     130           0 :         pwalletMain->MarkDirty();
     131           0 :         pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
     132             : 
     133             :         // Don't throw error in case a key is already there
     134           0 :         if (pwalletMain->HaveKey(vchAddress))
     135           0 :             return NullUniValue;
     136             : 
     137           0 :         pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
     138             : 
     139           0 :         if (!pwalletMain->AddKeyPubKey(key, pubkey))
     140           0 :             throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
     141             : 
     142             :         // whenever a key is imported, we need to scan the whole chain
     143           0 :         pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value'
     144             : 
     145           0 :         if (fRescan) {
     146           0 :             pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
     147             :         }
     148             :     }
     149             : 
     150           0 :     return NullUniValue;
     151             : }
     152             : 
     153             : void ImportAddress(const CBitcoinAddress& address, const string& strLabel);
     154           4 : void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript)
     155             : {
     156           4 :     if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
     157           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
     158             : 
     159           4 :     pwalletMain->MarkDirty();
     160             : 
     161           4 :     if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script))
     162           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
     163             : 
     164           4 :     if (isRedeemScript) {
     165           1 :         if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
     166           0 :             throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
     167           4 :         ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel);
     168             :     }
     169           4 : }
     170             : 
     171           2 : void ImportAddress(const CBitcoinAddress& address, const string& strLabel)
     172             : {
     173           4 :     CScript script = GetScriptForDestination(address.Get());
     174           2 :     ImportScript(script, strLabel, false);
     175             :     // add to address book or update label
     176           2 :     if (address.IsValid())
     177           8 :         pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
     178           2 : }
     179             : 
     180           1 : UniValue importaddress(const UniValue& params, bool fHelp)
     181             : {
     182           1 :     if (!EnsureWalletIsAvailable(fHelp))
     183           0 :         return NullUniValue;
     184             :     
     185           3 :     if (fHelp || params.size() < 1 || params.size() > 4)
     186             :         throw runtime_error(
     187             :             "importaddress \"address\" ( \"label\" rescan p2sh )\n"
     188             :             "\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend.\n"
     189             :             "\nArguments:\n"
     190             :             "1. \"script\"           (string, required) The hex-encoded script (or address)\n"
     191             :             "2. \"label\"            (string, optional, default=\"\") An optional label\n"
     192             :             "3. rescan               (boolean, optional, default=true) Rescan the wallet for transactions\n"
     193             :             "4. p2sh                 (boolean, optional, default=false) Add the P2SH version of the script as well\n"
     194             :             "\nNote: This call can take minutes to complete if rescan is true.\n"
     195             :             "If you have the full public key, you should call importpublickey instead of this.\n"
     196             :             "\nExamples:\n"
     197             :             "\nImport a script with rescan\n"
     198           0 :             + HelpExampleCli("importaddress", "\"myscript\"") +
     199             :             "\nImport using a label without rescan\n"
     200           0 :             + HelpExampleCli("importaddress", "\"myscript\" \"testing\" false") +
     201             :             "\nAs a JSON-RPC call\n"
     202           0 :             + HelpExampleRpc("importaddress", "\"myscript\", \"testing\", false")
     203           0 :         );
     204             : 
     205             : 
     206           2 :     string strLabel = "";
     207           1 :     if (params.size() > 1)
     208           2 :         strLabel = params[1].get_str();
     209             : 
     210             :     // Whether to perform rescan after import
     211           1 :     bool fRescan = true;
     212           1 :     if (params.size() > 2)
     213           1 :         fRescan = params[2].get_bool();
     214             : 
     215           1 :     if (fRescan && fPruneMode)
     216           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
     217             : 
     218             :     // Whether to import a p2sh version, too
     219           1 :     bool fP2SH = false;
     220           1 :     if (params.size() > 3)
     221           1 :         fP2SH = params[3].get_bool();
     222             : 
     223           1 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     224             : 
     225           2 :     CBitcoinAddress address(params[0].get_str());
     226           1 :     if (address.IsValid()) {
     227           0 :         if (fP2SH)
     228           0 :             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
     229           0 :         ImportAddress(address, strLabel);
     230           2 :     } else if (IsHex(params[0].get_str())) {
     231           2 :         std::vector<unsigned char> data(ParseHex(params[0].get_str()));
     232           5 :         ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
     233             :     } else {
     234           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
     235             :     }
     236             : 
     237           1 :     if (fRescan)
     238             :     {
     239           0 :         pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
     240           0 :         pwalletMain->ReacceptWalletTransactions();
     241             :     }
     242             : 
     243           1 :     return NullUniValue;
     244             : }
     245             : 
     246           1 : UniValue importpubkey(const UniValue& params, bool fHelp)
     247             : {
     248           1 :     if (!EnsureWalletIsAvailable(fHelp))
     249           0 :         return NullUniValue;
     250             : 
     251           3 :     if (fHelp || params.size() < 1 || params.size() > 4)
     252             :         throw runtime_error(
     253             :             "importpubkey \"pubkey\" ( \"label\" rescan )\n"
     254             :             "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n"
     255             :             "\nArguments:\n"
     256             :             "1. \"pubkey\"           (string, required) The hex-encoded public key\n"
     257             :             "2. \"label\"            (string, optional, default=\"\") An optional label\n"
     258             :             "3. rescan               (boolean, optional, default=true) Rescan the wallet for transactions\n"
     259             :             "\nNote: This call can take minutes to complete if rescan is true.\n"
     260             :             "\nExamples:\n"
     261             :             "\nImport a public key with rescan\n"
     262           0 :             + HelpExampleCli("importpubkey", "\"mypubkey\"") +
     263             :             "\nImport using a label without rescan\n"
     264           0 :             + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
     265             :             "\nAs a JSON-RPC call\n"
     266           0 :             + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
     267           0 :         );
     268             : 
     269             : 
     270           2 :     string strLabel = "";
     271           1 :     if (params.size() > 1)
     272           2 :         strLabel = params[1].get_str();
     273             : 
     274             :     // Whether to perform rescan after import
     275           1 :     bool fRescan = true;
     276           1 :     if (params.size() > 2)
     277           1 :         fRescan = params[2].get_bool();
     278             : 
     279           1 :     if (fRescan && fPruneMode)
     280           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
     281             : 
     282           2 :     if (!IsHex(params[0].get_str()))
     283           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
     284           2 :     std::vector<unsigned char> data(ParseHex(params[0].get_str()));
     285             :     CPubKey pubKey(data.begin(), data.end());
     286           1 :     if (!pubKey.IsFullyValid())
     287           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
     288             : 
     289           1 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     290             : 
     291           4 :     ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
     292           2 :     ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
     293             : 
     294           1 :     if (fRescan)
     295             :     {
     296           1 :         pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
     297           1 :         pwalletMain->ReacceptWalletTransactions();
     298             :     }
     299             : 
     300           1 :     return NullUniValue;
     301             : }
     302             : 
     303             : 
     304           3 : UniValue importwallet(const UniValue& params, bool fHelp)
     305             : {
     306           3 :     if (!EnsureWalletIsAvailable(fHelp))
     307           0 :         return NullUniValue;
     308             :     
     309           6 :     if (fHelp || params.size() != 1)
     310             :         throw runtime_error(
     311             :             "importwallet \"filename\"\n"
     312             :             "\nImports keys from a wallet dump file (see dumpwallet).\n"
     313             :             "\nArguments:\n"
     314             :             "1. \"filename\"    (string, required) The wallet file\n"
     315             :             "\nExamples:\n"
     316             :             "\nDump the wallet\n"
     317           0 :             + HelpExampleCli("dumpwallet", "\"test\"") +
     318             :             "\nImport the wallet\n"
     319           0 :             + HelpExampleCli("importwallet", "\"test\"") +
     320             :             "\nImport using the json rpc call\n"
     321           0 :             + HelpExampleRpc("importwallet", "\"test\"")
     322           0 :         );
     323             : 
     324           3 :     if (fPruneMode)
     325           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
     326             : 
     327           3 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     328             : 
     329           3 :     EnsureWalletIsUnlocked();
     330             : 
     331           6 :     ifstream file;
     332           9 :     file.open(params[0].get_str().c_str(), std::ios::in | std::ios::ate);
     333           3 :     if (!file.is_open())
     334           0 :         throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
     335             : 
     336           6 :     int64_t nTimeBegin = chainActive.Tip()->GetBlockTime();
     337             : 
     338           3 :     bool fGood = true;
     339             : 
     340           6 :     int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
     341           3 :     file.seekg(0, file.beg);
     342             : 
     343           6 :     pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
     344         367 :     while (file.good()) {
     345        1805 :         pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
     346             :         std::string line;
     347         361 :         std::getline(file, line);
     348         713 :         if (line.empty() || line[0] == '#')
     349             :             continue;
     350             : 
     351         337 :         std::vector<std::string> vstr;
     352         337 :         boost::split(vstr, line, boost::is_any_of(" "));
     353         674 :         if (vstr.size() < 2)
     354           0 :             continue;
     355             :         CBitcoinSecret vchSecret;
     356         337 :         if (!vchSecret.SetString(vstr[0]))
     357             :             continue;
     358         337 :         CKey key = vchSecret.GetKey();
     359         337 :         CPubKey pubkey = key.GetPubKey();
     360         337 :         assert(key.VerifyPubKey(pubkey));
     361         337 :         CKeyID keyid = pubkey.GetID();
     362         337 :         if (pwalletMain->HaveKey(keyid)) {
     363           0 :             LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
     364           0 :             continue;
     365             :         }
     366         674 :         int64_t nTime = DecodeDumpTime(vstr[1]);
     367             :         std::string strLabel;
     368         337 :         bool fLabel = true;
     369        1348 :         for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
     370        2022 :             if (boost::algorithm::starts_with(vstr[nStr], "#"))
     371             :                 break;
     372         674 :             if (vstr[nStr] == "change=1")
     373          19 :                 fLabel = false;
     374        1011 :             if (vstr[nStr] == "reserve=1")
     375         300 :                 fLabel = false;
     376        1011 :             if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
     377          54 :                 strLabel = DecodeDumpString(vstr[nStr].substr(6));
     378          18 :                 fLabel = true;
     379             :             }
     380             :         }
     381        1348 :         LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
     382         337 :         if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
     383           0 :             fGood = false;
     384             :             continue;
     385             :         }
     386         337 :         pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
     387         337 :         if (fLabel)
     388          90 :             pwalletMain->SetAddressBook(keyid, strLabel, "receive");
     389         337 :         nTimeBegin = std::min(nTimeBegin, nTime);
     390             :     }
     391           3 :     file.close();
     392           9 :     pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
     393             : 
     394           3 :     CBlockIndex *pindex = chainActive.Tip();
     395        1290 :     while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200)
     396         642 :         pindex = pindex->pprev;
     397             : 
     398           3 :     if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey)
     399           3 :         pwalletMain->nTimeFirstKey = nTimeBegin;
     400             : 
     401           3 :     LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1);
     402           3 :     pwalletMain->ScanForWalletTransactions(pindex);
     403           3 :     pwalletMain->MarkDirty();
     404             : 
     405           3 :     if (!fGood)
     406           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
     407             : 
     408           3 :     return NullUniValue;
     409             : }
     410             : 
     411           0 : UniValue dumpprivkey(const UniValue& params, bool fHelp)
     412             : {
     413           0 :     if (!EnsureWalletIsAvailable(fHelp))
     414           0 :         return NullUniValue;
     415             :     
     416           0 :     if (fHelp || params.size() != 1)
     417             :         throw runtime_error(
     418             :             "dumpprivkey \"bitcoinaddress\"\n"
     419             :             "\nReveals the private key corresponding to 'bitcoinaddress'.\n"
     420             :             "Then the importprivkey can be used with this output\n"
     421             :             "\nArguments:\n"
     422             :             "1. \"bitcoinaddress\"   (string, required) The bitcoin address for the private key\n"
     423             :             "\nResult:\n"
     424             :             "\"key\"                (string) The private key\n"
     425             :             "\nExamples:\n"
     426           0 :             + HelpExampleCli("dumpprivkey", "\"myaddress\"")
     427           0 :             + HelpExampleCli("importprivkey", "\"mykey\"")
     428           0 :             + HelpExampleRpc("dumpprivkey", "\"myaddress\"")
     429           0 :         );
     430             : 
     431           0 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     432             : 
     433           0 :     EnsureWalletIsUnlocked();
     434             : 
     435           0 :     string strAddress = params[0].get_str();
     436             :     CBitcoinAddress address;
     437           0 :     if (!address.SetString(strAddress))
     438           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
     439             :     CKeyID keyID;
     440           0 :     if (!address.GetKeyID(keyID))
     441           0 :         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
     442             :     CKey vchSecret;
     443           0 :     if (!pwalletMain->GetKey(keyID, vchSecret))
     444           0 :         throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
     445           0 :     return CBitcoinSecret(vchSecret).ToString();
     446             : }
     447             : 
     448             : 
     449           3 : UniValue dumpwallet(const UniValue& params, bool fHelp)
     450             : {
     451           3 :     if (!EnsureWalletIsAvailable(fHelp))
     452           0 :         return NullUniValue;
     453             :     
     454           6 :     if (fHelp || params.size() != 1)
     455             :         throw runtime_error(
     456             :             "dumpwallet \"filename\"\n"
     457             :             "\nDumps all wallet keys in a human-readable format.\n"
     458             :             "\nArguments:\n"
     459             :             "1. \"filename\"    (string, required) The filename\n"
     460             :             "\nExamples:\n"
     461           0 :             + HelpExampleCli("dumpwallet", "\"test\"")
     462           0 :             + HelpExampleRpc("dumpwallet", "\"test\"")
     463           0 :         );
     464             : 
     465           3 :     LOCK2(cs_main, pwalletMain->cs_wallet);
     466             : 
     467           3 :     EnsureWalletIsUnlocked();
     468             : 
     469           6 :     ofstream file;
     470           9 :     file.open(params[0].get_str().c_str());
     471           3 :     if (!file.is_open())
     472           0 :         throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
     473             : 
     474             :     std::map<CKeyID, int64_t> mapKeyBirth;
     475             :     std::set<CKeyID> setKeyPool;
     476           3 :     pwalletMain->GetKeyBirthTimes(mapKeyBirth);
     477           3 :     pwalletMain->GetAllReserveKeys(setKeyPool);
     478             : 
     479             :     // sort time/key pairs
     480             :     std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
     481         683 :     for (std::map<CKeyID, int64_t>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
     482        1011 :         vKeyBirth.push_back(std::make_pair(it->second, it->first));
     483             :     }
     484             :     mapKeyBirth.clear();
     485             :     std::sort(vKeyBirth.begin(), vKeyBirth.end());
     486             : 
     487             :     // produce output
     488           6 :     file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE);
     489          12 :     file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
     490          15 :     file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
     491          15 :     file << strprintf("#   mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
     492           3 :     file << "\n";
     493        1023 :     for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
     494         337 :         const CKeyID &keyid = it->second;
     495         337 :         std::string strTime = EncodeDumpTime(it->first);
     496        1011 :         std::string strAddr = CBitcoinAddress(keyid).ToString();
     497             :         CKey key;
     498         337 :         if (pwalletMain->GetKey(keyid, key)) {
     499        1011 :             if (pwalletMain->mapAddressBook.count(keyid)) {
     500         108 :                 file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
     501         319 :             } else if (setKeyPool.count(keyid)) {
     502        1200 :                 file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
     503             :             } else {
     504          76 :                 file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
     505             :             }
     506             :         }
     507             :     }
     508           3 :     file << "\n";
     509           3 :     file << "# End of dump\n";
     510           3 :     file.close();
     511           3 :     return NullUniValue;
     512         288 : }

Generated by: LCOV version 1.11