Dash Core  0.12.2.1
P2P Digital Currency
rpcdump.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2017 The Dash Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "base58.h"
7 #include "chain.h"
8 #include "rpc/server.h"
9 #include "init.h"
10 #include "validation.h"
11 #include "script/script.h"
12 #include "script/standard.h"
13 #include "sync.h"
14 #include "util.h"
15 #include "utiltime.h"
16 #include "wallet.h"
17 
18 #include <fstream>
19 #include <stdint.h>
20 
21 #include <boost/algorithm/string.hpp>
22 #include <boost/date_time/posix_time/posix_time.hpp>
23 
24 #include <univalue.h>
25 
26 #include <boost/foreach.hpp>
27 
28 using namespace std;
29 
31 bool EnsureWalletIsAvailable(bool avoidException);
32 
33 std::string static EncodeDumpTime(int64_t nTime) {
34  return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
35 }
36 
37 int64_t static DecodeDumpTime(const std::string &str) {
38  static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
39  static const std::locale loc(std::locale::classic(),
40  new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
41  std::istringstream iss(str);
42  iss.imbue(loc);
43  boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
44  iss >> ptime;
45  if (ptime.is_not_a_date_time())
46  return 0;
47  return (ptime - epoch).total_seconds();
48 }
49 
50 std::string static EncodeDumpString(const std::string &str) {
51  std::stringstream ret;
52  BOOST_FOREACH(unsigned char c, str) {
53  if (c <= 32 || c >= 128 || c == '%') {
54  ret << '%' << HexStr(&c, &c + 1);
55  } else {
56  ret << c;
57  }
58  }
59  return ret.str();
60 }
61 
62 std::string DecodeDumpString(const std::string &str) {
63  std::stringstream ret;
64  for (unsigned int pos = 0; pos < str.length(); pos++) {
65  unsigned char c = str[pos];
66  if (c == '%' && pos+2 < str.length()) {
67  c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
68  ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
69  pos += 2;
70  }
71  ret << c;
72  }
73  return ret.str();
74 }
75 
76 UniValue importprivkey(const UniValue& params, bool fHelp)
77 {
78  if (!EnsureWalletIsAvailable(fHelp))
79  return NullUniValue;
80 
81  if (fHelp || params.size() < 1 || params.size() > 3)
82  throw runtime_error(
83  "importprivkey \"dashprivkey\" ( \"label\" rescan )\n"
84  "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
85  "\nArguments:\n"
86  "1. \"dashprivkey\" (string, required) The private key (see dumpprivkey)\n"
87  "2. \"label\" (string, optional, default=\"\") An optional label\n"
88  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
89  "\nNote: This call can take minutes to complete if rescan is true.\n"
90  "\nExamples:\n"
91  "\nDump a private key\n"
92  + HelpExampleCli("dumpprivkey", "\"myaddress\"") +
93  "\nImport the private key with rescan\n"
94  + HelpExampleCli("importprivkey", "\"mykey\"") +
95  "\nImport using a label and without rescan\n"
96  + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
97  "\nAs a JSON-RPC call\n"
98  + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
99  );
100 
101 
103 
105 
106  string strSecret = params[0].get_str();
107  string strLabel = "";
108  if (params.size() > 1)
109  strLabel = params[1].get_str();
110 
111  // Whether to perform rescan after import
112  bool fRescan = true;
113  if (params.size() > 2)
114  fRescan = params[2].get_bool();
115 
116  if (fRescan && fPruneMode)
117  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
118 
119  CBitcoinSecret vchSecret;
120  bool fGood = vchSecret.SetString(strSecret);
121 
122  if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
123 
124  CKey key = vchSecret.GetKey();
125  if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
126 
127  CPubKey pubkey = key.GetPubKey();
128  assert(key.VerifyPubKey(pubkey));
129  CKeyID vchAddress = pubkey.GetID();
130  {
132  pwalletMain->SetAddressBook(vchAddress, strLabel, "receive");
133 
134  // Don't throw error in case a key is already there
135  if (pwalletMain->HaveKey(vchAddress))
136  return NullUniValue;
137 
138  pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
139 
140  if (!pwalletMain->AddKeyPubKey(key, pubkey))
141  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
142 
143  // whenever a key is imported, we need to scan the whole chain
144  pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value'
145 
146  if (fRescan) {
148  }
149  }
150 
151  return NullUniValue;
152 }
153 
154 void ImportAddress(const CBitcoinAddress& address, const string& strLabel);
155 void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript)
156 {
157  if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
158  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
159 
161 
162  if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script))
163  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
164 
165  if (isRedeemScript) {
166  if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
167  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
168  ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel);
169  }
170 }
171 
172 void ImportAddress(const CBitcoinAddress& address, const string& strLabel)
173 {
174  CScript script = GetScriptForDestination(address.Get());
175  ImportScript(script, strLabel, false);
176  // add to address book or update label
177  if (address.IsValid())
178  pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
179 }
180 
181 UniValue importaddress(const UniValue& params, bool fHelp)
182 {
183  if (!EnsureWalletIsAvailable(fHelp))
184  return NullUniValue;
185 
186  if (fHelp || params.size() < 1 || params.size() > 4)
187  throw runtime_error(
188  "importaddress \"address\" ( \"label\" rescan p2sh )\n"
189  "\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"
190  "\nArguments:\n"
191  "1. \"script\" (string, required) The hex-encoded script (or address)\n"
192  "2. \"label\" (string, optional, default=\"\") An optional label\n"
193  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
194  "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
195  "\nNote: This call can take minutes to complete if rescan is true.\n"
196  "If you have the full public key, you should call importpublickey instead of this.\n"
197  "\nExamples:\n"
198  "\nImport a script with rescan\n"
199  + HelpExampleCli("importaddress", "\"myscript\"") +
200  "\nImport using a label without rescan\n"
201  + HelpExampleCli("importaddress", "\"myscript\" \"testing\" false") +
202  "\nAs a JSON-RPC call\n"
203  + HelpExampleRpc("importaddress", "\"myscript\", \"testing\", false")
204  );
205 
206 
207  string strLabel = "";
208  if (params.size() > 1)
209  strLabel = params[1].get_str();
210 
211  // Whether to perform rescan after import
212  bool fRescan = true;
213  if (params.size() > 2)
214  fRescan = params[2].get_bool();
215 
216  if (fRescan && fPruneMode)
217  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
218 
219  // Whether to import a p2sh version, too
220  bool fP2SH = false;
221  if (params.size() > 3)
222  fP2SH = params[3].get_bool();
223 
225 
226  CBitcoinAddress address(params[0].get_str());
227  if (address.IsValid()) {
228  if (fP2SH)
229  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
230  ImportAddress(address, strLabel);
231  } else if (IsHex(params[0].get_str())) {
232  std::vector<unsigned char> data(ParseHex(params[0].get_str()));
233  ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
234  } else {
235  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address or script");
236  }
237 
238  if (fRescan)
239  {
242  }
243 
244  return NullUniValue;
245 }
246 
247 UniValue importpubkey(const UniValue& params, bool fHelp)
248 {
249  if (!EnsureWalletIsAvailable(fHelp))
250  return NullUniValue;
251 
252  if (fHelp || params.size() < 1 || params.size() > 4)
253  throw runtime_error(
254  "importpubkey \"pubkey\" ( \"label\" rescan )\n"
255  "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n"
256  "\nArguments:\n"
257  "1. \"pubkey\" (string, required) The hex-encoded public key\n"
258  "2. \"label\" (string, optional, default=\"\") An optional label\n"
259  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
260  "\nNote: This call can take minutes to complete if rescan is true.\n"
261  "\nExamples:\n"
262  "\nImport a public key with rescan\n"
263  + HelpExampleCli("importpubkey", "\"mypubkey\"") +
264  "\nImport using a label without rescan\n"
265  + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
266  "\nAs a JSON-RPC call\n"
267  + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
268  );
269 
270 
271  string strLabel = "";
272  if (params.size() > 1)
273  strLabel = params[1].get_str();
274 
275  // Whether to perform rescan after import
276  bool fRescan = true;
277  if (params.size() > 2)
278  fRescan = params[2].get_bool();
279 
280  if (fRescan && fPruneMode)
281  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
282 
283  if (!IsHex(params[0].get_str()))
284  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
285  std::vector<unsigned char> data(ParseHex(params[0].get_str()));
286  CPubKey pubKey(data.begin(), data.end());
287  if (!pubKey.IsFullyValid())
288  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
289 
291 
292  ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
293  ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
294 
295  if (fRescan)
296  {
299  }
300 
301  return NullUniValue;
302 }
303 
304 
305 UniValue importwallet(const UniValue& params, bool fHelp)
306 {
307  if (!EnsureWalletIsAvailable(fHelp))
308  return NullUniValue;
309 
310  if (fHelp || params.size() != 1)
311  throw runtime_error(
312  "importwallet \"filename\"\n"
313  "\nImports keys from a wallet dump file (see dumpwallet).\n"
314  "\nArguments:\n"
315  "1. \"filename\" (string, required) The wallet file\n"
316  "\nExamples:\n"
317  "\nDump the wallet\n"
318  + HelpExampleCli("dumpwallet", "\"test\"") +
319  "\nImport the wallet\n"
320  + HelpExampleCli("importwallet", "\"test\"") +
321  "\nImport using the json rpc call\n"
322  + HelpExampleRpc("importwallet", "\"test\"")
323  );
324 
325  if (fPruneMode)
326  throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
327 
329 
331 
332  ifstream file;
333  file.open(params[0].get_str().c_str(), std::ios::in | std::ios::ate);
334  if (!file.is_open())
335  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
336 
337  int64_t nTimeBegin = chainActive.Tip()->GetBlockTime();
338 
339  bool fGood = true;
340 
341  int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
342  file.seekg(0, file.beg);
343 
344  pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
345  while (file.good()) {
346  pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
347  std::string line;
348  std::getline(file, line);
349  if (line.empty() || line[0] == '#')
350  continue;
351 
352  std::vector<std::string> vstr;
353  boost::split(vstr, line, boost::is_any_of(" "));
354  if (vstr.size() < 2)
355  continue;
356  CBitcoinSecret vchSecret;
357  if (!vchSecret.SetString(vstr[0]))
358  continue;
359  CKey key = vchSecret.GetKey();
360  CPubKey pubkey = key.GetPubKey();
361  assert(key.VerifyPubKey(pubkey));
362  CKeyID keyid = pubkey.GetID();
363  if (pwalletMain->HaveKey(keyid)) {
364  LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
365  continue;
366  }
367  int64_t nTime = DecodeDumpTime(vstr[1]);
368  std::string strLabel;
369  bool fLabel = true;
370  for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
371  if (boost::algorithm::starts_with(vstr[nStr], "#"))
372  break;
373  if (vstr[nStr] == "change=1")
374  fLabel = false;
375  if (vstr[nStr] == "reserve=1")
376  fLabel = false;
377  if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
378  strLabel = DecodeDumpString(vstr[nStr].substr(6));
379  fLabel = true;
380  }
381  }
382  LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
383  if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
384  fGood = false;
385  continue;
386  }
387  pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
388  if (fLabel)
389  pwalletMain->SetAddressBook(keyid, strLabel, "receive");
390  nTimeBegin = std::min(nTimeBegin, nTime);
391  }
392  file.close();
393  pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
394 
395  CBlockIndex *pindex = chainActive.Tip();
396  while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200)
397  pindex = pindex->pprev;
398 
399  if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey)
400  pwalletMain->nTimeFirstKey = nTimeBegin;
401 
402  LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1);
405 
406  if (!fGood)
407  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
408 
409  return NullUniValue;
410 }
411 
412 UniValue importelectrumwallet(const UniValue& params, bool fHelp)
413 {
414  if (!EnsureWalletIsAvailable(fHelp))
415  return NullUniValue;
416 
417  if (fHelp || params.size() < 1 || params.size() > 2)
418  throw runtime_error(
419  "importelectrumwallet \"filename\" index\n"
420  "\nImports keys from an Electrum wallet export file (.csv or .json)\n"
421  "\nArguments:\n"
422  "1. \"filename\" (string, required) The Electrum wallet export file, should be in csv or json format\n"
423  "2. index (numeric, optional, default=0) Rescan the wallet for transactions starting from this block index\n"
424  "\nExamples:\n"
425  "\nImport the wallet\n"
426  + HelpExampleCli("importelectrumwallet", "\"test.csv\"")
427  + HelpExampleCli("importelectrumwallet", "\"test.json\"") +
428  "\nImport using the json rpc call\n"
429  + HelpExampleRpc("importelectrumwallet", "\"test.csv\"")
430  + HelpExampleRpc("importelectrumwallet", "\"test.json\"")
431  );
432 
433  if (fPruneMode)
434  throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
435 
437 
439 
440  ifstream file;
441  std::string strFileName = params[0].get_str();
442  size_t nDotPos = strFileName.find_last_of(".");
443  if(nDotPos == string::npos)
444  throw JSONRPCError(RPC_INVALID_PARAMETER, "File has no extension, should be .json or .csv");
445 
446  std::string strFileExt = strFileName.substr(nDotPos+1);
447  if(strFileExt != "json" && strFileExt != "csv")
448  throw JSONRPCError(RPC_INVALID_PARAMETER, "File has wrong extension, should be .json or .csv");
449 
450  file.open(strFileName.c_str(), std::ios::in | std::ios::ate);
451  if (!file.is_open())
452  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open Electrum wallet export file");
453 
454  bool fGood = true;
455 
456  int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
457  file.seekg(0, file.beg);
458 
459  pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
460 
461  if(strFileExt == "csv") {
462  while (file.good()) {
463  pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
464  std::string line;
465  std::getline(file, line);
466  if (line.empty() || line == "address,private_key")
467  continue;
468  std::vector<std::string> vstr;
469  boost::split(vstr, line, boost::is_any_of(","));
470  if (vstr.size() < 2)
471  continue;
472  CBitcoinSecret vchSecret;
473  if (!vchSecret.SetString(vstr[1]))
474  continue;
475  CKey key = vchSecret.GetKey();
476  CPubKey pubkey = key.GetPubKey();
477  assert(key.VerifyPubKey(pubkey));
478  CKeyID keyid = pubkey.GetID();
479  if (pwalletMain->HaveKey(keyid)) {
480  LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
481  continue;
482  }
483  LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
484  if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
485  fGood = false;
486  continue;
487  }
488  }
489  } else {
490  // json
491  char* buffer = new char [nFilesize];
492  file.read(buffer, nFilesize);
494  if(!data.read(buffer))
495  throw JSONRPCError(RPC_TYPE_ERROR, "Cannot parse Electrum wallet export file");
496  delete[] buffer;
497 
498  std::vector<std::string> vKeys = data.getKeys();
499 
500  for (size_t i = 0; i < data.size(); i++) {
501  pwalletMain->ShowProgress("", std::max(1, std::min(99, int(i*100/data.size()))));
502  if(!data[vKeys[i]].isStr())
503  continue;
504  CBitcoinSecret vchSecret;
505  if (!vchSecret.SetString(data[vKeys[i]].get_str()))
506  continue;
507  CKey key = vchSecret.GetKey();
508  CPubKey pubkey = key.GetPubKey();
509  assert(key.VerifyPubKey(pubkey));
510  CKeyID keyid = pubkey.GetID();
511  if (pwalletMain->HaveKey(keyid)) {
512  LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
513  continue;
514  }
515  LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
516  if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
517  fGood = false;
518  continue;
519  }
520  }
521  }
522  file.close();
523  pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI
524 
525  // Whether to perform rescan after import
526  int nStartHeight = 0;
527  if (params.size() > 1)
528  nStartHeight = params[1].get_int();
529  if (chainActive.Height() < nStartHeight)
530  nStartHeight = chainActive.Height();
531 
532  // Assume that electrum wallet was created at that block
533  int nTimeBegin = chainActive[nStartHeight]->GetBlockTime();
534  if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey)
535  pwalletMain->nTimeFirstKey = nTimeBegin;
536 
537  LogPrintf("Rescanning %i blocks\n", chainActive.Height() - nStartHeight + 1);
538  pwalletMain->ScanForWalletTransactions(chainActive[nStartHeight], true);
539 
540  if (!fGood)
541  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
542 
543  return NullUniValue;
544 }
545 
546 UniValue dumpprivkey(const UniValue& params, bool fHelp)
547 {
548  if (!EnsureWalletIsAvailable(fHelp))
549  return NullUniValue;
550 
551  if (fHelp || params.size() != 1)
552  throw runtime_error(
553  "dumpprivkey \"dashaddress\"\n"
554  "\nReveals the private key corresponding to 'dashaddress'.\n"
555  "Then the importprivkey can be used with this output\n"
556  "\nArguments:\n"
557  "1. \"dashaddress\" (string, required) The dash address for the private key\n"
558  "\nResult:\n"
559  "\"key\" (string) The private key\n"
560  "\nExamples:\n"
561  + HelpExampleCli("dumpprivkey", "\"myaddress\"")
562  + HelpExampleCli("importprivkey", "\"mykey\"")
563  + HelpExampleRpc("dumpprivkey", "\"myaddress\"")
564  );
565 
567 
569 
570  string strAddress = params[0].get_str();
571  CBitcoinAddress address;
572  if (!address.SetString(strAddress))
573  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
574  CKeyID keyID;
575  if (!address.GetKeyID(keyID))
576  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
577  CKey vchSecret;
578  if (!pwalletMain->GetKey(keyID, vchSecret))
579  throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
580  return CBitcoinSecret(vchSecret).ToString();
581 }
582 
583 UniValue dumphdinfo(const UniValue& params, bool fHelp)
584 {
585  if (!EnsureWalletIsAvailable(fHelp))
586  return NullUniValue;
587 
588  if (fHelp || params.size() != 0)
589  throw runtime_error(
590  "dumphdinfo\n"
591  "Returns an object containing sensitive private info about this HD wallet.\n"
592  "\nResult:\n"
593  "{\n"
594  " \"hdseed\": \"seed\", (string) The HD seed (bip32, in hex)\n"
595  " \"mnemonic\": \"words\", (string) The mnemonic for this HD wallet (bip39, english words) \n"
596  " \"mnemonicpassphrase\": \"passphrase\", (string) The mnemonic passphrase for this HD wallet (bip39)\n"
597  "}\n"
598  "\nExamples:\n"
599  + HelpExampleCli("dumphdinfo", "")
600  + HelpExampleRpc("dumphdinfo", "")
601  );
602 
604 
606 
607  // add the base58check encoded extended master if the wallet uses HD
608  CHDChain hdChainCurrent;
609  if (pwalletMain->GetHDChain(hdChainCurrent))
610  {
611  if (!pwalletMain->GetDecryptedHDChain(hdChainCurrent))
612  throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD seed");
613 
614  SecureString ssMnemonic;
615  SecureString ssMnemonicPassphrase;
616  hdChainCurrent.GetMnemonic(ssMnemonic, ssMnemonicPassphrase);
617 
619  obj.push_back(Pair("hdseed", HexStr(hdChainCurrent.GetSeed())));
620  obj.push_back(Pair("mnemonic", ssMnemonic.c_str()));
621  obj.push_back(Pair("mnemonicpassphrase", ssMnemonicPassphrase.c_str()));
622 
623  return obj;
624  }
625 
626  return NullUniValue;
627 }
628 
629 UniValue dumpwallet(const UniValue& params, bool fHelp)
630 {
631  if (!EnsureWalletIsAvailable(fHelp))
632  return NullUniValue;
633 
634  if (fHelp || params.size() != 1)
635  throw runtime_error(
636  "dumpwallet \"filename\"\n"
637  "\nDumps all wallet keys in a human-readable format.\n"
638  "\nArguments:\n"
639  "1. \"filename\" (string, required) The filename\n"
640  "\nExamples:\n"
641  + HelpExampleCli("dumpwallet", "\"test\"")
642  + HelpExampleRpc("dumpwallet", "\"test\"")
643  );
644 
646 
648 
649  ofstream file;
650  file.open(params[0].get_str().c_str());
651  if (!file.is_open())
652  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
653 
654  std::map<CKeyID, int64_t> mapKeyBirth;
655  std::set<CKeyID> setKeyPool;
656  pwalletMain->GetKeyBirthTimes(mapKeyBirth);
657  pwalletMain->GetAllReserveKeys(setKeyPool);
658 
659  // sort time/key pairs
660  std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
661  for (std::map<CKeyID, int64_t>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
662  vKeyBirth.push_back(std::make_pair(it->second, it->first));
663  }
664  mapKeyBirth.clear();
665  std::sort(vKeyBirth.begin(), vKeyBirth.end());
666 
667  // produce output
668  file << strprintf("# Wallet dump created by Dash Core %s (%s)\n", CLIENT_BUILD, CLIENT_DATE);
669  file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
670  file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
671  file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
672  file << "\n";
673 
674  // add the base58check encoded extended master if the wallet uses HD
675  CHDChain hdChainCurrent;
676  if (pwalletMain->GetHDChain(hdChainCurrent))
677  {
678 
679  if (!pwalletMain->GetDecryptedHDChain(hdChainCurrent))
680  throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD chain");
681 
682  SecureString ssMnemonic;
683  SecureString ssMnemonicPassphrase;
684  hdChainCurrent.GetMnemonic(ssMnemonic, ssMnemonicPassphrase);
685  file << "# mnemonic: " << ssMnemonic << "\n";
686  file << "# mnemonic passphrase: " << ssMnemonicPassphrase << "\n\n";
687 
688  SecureVector vchSeed = hdChainCurrent.GetSeed();
689  file << "# HD seed: " << HexStr(vchSeed) << "\n\n";
690 
691  CExtKey masterKey;
692  masterKey.SetMaster(&vchSeed[0], vchSeed.size());
693 
694  CBitcoinExtKey b58extkey;
695  b58extkey.SetKey(masterKey);
696 
697  file << "# extended private masterkey: " << b58extkey.ToString() << "\n";
698 
699  CExtPubKey masterPubkey;
700  masterPubkey = masterKey.Neuter();
701 
702  CBitcoinExtPubKey b58extpubkey;
703  b58extpubkey.SetKey(masterPubkey);
704  file << "# extended public masterkey: " << b58extpubkey.ToString() << "\n\n";
705 
706  for (size_t i = 0; i < hdChainCurrent.CountAccounts(); ++i)
707  {
708  CHDAccount acc;
709  if(hdChainCurrent.GetAccount(i, acc)) {
710  file << "# external chain counter: " << acc.nExternalChainCounter << "\n";
711  file << "# internal chain counter: " << acc.nInternalChainCounter << "\n\n";
712  } else {
713  file << "# WARNING: ACCOUNT " << i << " IS MISSING!" << "\n\n";
714  }
715  }
716  }
717 
718  for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
719  const CKeyID &keyid = it->second;
720  std::string strTime = EncodeDumpTime(it->first);
721  std::string strAddr = CBitcoinAddress(keyid).ToString();
722  CKey key;
723  if (pwalletMain->GetKey(keyid, key)) {
724  file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
725  if (pwalletMain->mapAddressBook.count(keyid)) {
726  file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name));
727  } else if (setKeyPool.count(keyid)) {
728  file << "reserve=1";
729  } else {
730  file << "change=1";
731  }
732  file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapHdPubKeys.count(keyid) ? " hdkeypath="+pwalletMain->mapHdPubKeys[keyid].GetKeyPath() : ""));
733  }
734  }
735  file << "\n";
736  file << "# End of dump\n";
737  file.close();
738  return NullUniValue;
739 }
static std::string EncodeDumpString(const std::string &str)
Definition: rpcdump.cpp:50
bool SetString(const char *pszSecret)
Definition: base58.cpp:329
std::string DecodeDumpString(const std::string &str)
Definition: rpcdump.cpp:62
bool fPruneMode
Definition: validation.cpp:77
void SetMaster(const unsigned char *seed, unsigned int nSeedLen)
Definition: key.cpp:255
static int64_t DecodeDumpTime(const std::string &str)
Definition: rpcdump.cpp:37
UniValue importaddress(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:181
UniValue importprivkey(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:76
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3683
bool IsValid() const
Definition: base58.cpp:247
#define strprintf
Definition: tinyformat.h:1011
void ImportScript(const CScript &script, const string &strLabel, bool isRedeemScript)
Definition: rpcdump.cpp:155
CCriticalSection cs_wallet
Definition: wallet.h:672
bool GetMnemonic(SecureVector &vchMnemonicRet, SecureVector &vchMnemonicPassphraseRet) const
Definition: hdchain.cpp:107
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
Definition: utiltime.cpp:81
CCriticalSection cs_main
Definition: validation.cpp:62
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:61
SecureVector GetSeed() const
Definition: hdchain.cpp:141
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Definition: standard.cpp:270
Definition: pubkey.h:27
bool GetDecryptedHDChain(CHDChain &hdChainRet)
Definition: wallet.cpp:1464
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: server.cpp:586
uint32_t nInternalChainCounter
Definition: hdchain.h:14
CWallet * pwalletMain
bool IsHex(const string &str)
size_t CountAccounts()
Definition: hdchain.cpp:203
void ImportAddress(const CBitcoinAddress &address, const string &strLabel)
Definition: rpcdump.cpp:172
UniValue importpubkey(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:247
bool push_back(const UniValue &val)
Definition: univalue.cpp:176
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:144
Ran out of memory during operation.
Definition: protocol.h:46
std::string ToString() const
Definition: base58.cpp:193
bool AddCScript(const CScript &redeemScript)
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
Definition: wallet.cpp:349
bool GetKey(const CKeyID &address, CKey &keyOut) const
GetKey implementation that can derive a HD private key on the fly.
Definition: wallet.cpp:216
bool GetAccount(uint32_t nAccountIndex, CHDAccount &hdAccountRet)
Definition: hdchain.cpp:184
bool GetHDChain(CHDChain &hdChainRet) const
Definition: crypter.cpp:525
#define LOCK2(cs1, cs2)
Definition: sync.h:169
#define LogPrintf(...)
Definition: util.h:98
CExtPubKey Neuter() const
Definition: key.cpp:268
bool AddWatchOnly(const CScript &dest)
Adds a watch-only address to the store, and saves it to disk.
Definition: wallet.cpp:374
std::map< CKeyID, CKeyMetadata > mapKeyMetadata
Definition: wallet.h:695
void EnsureWalletIsUnlocked()
Definition: rpcwallet.cpp:54
#define LOCK(cs)
Definition: sync.h:168
UniValue importelectrumwallet(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:412
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Definition: wallet.h:1021
bool HaveKey(const CKeyID &address) const
HaveKey implementation that also checks the mapHdPubKeys.
Definition: wallet.cpp:244
std::vector< unsigned char, secure_allocator< unsigned char > > SecureVector
Definition: secure.h:63
uint32_t nExternalChainCounter
Definition: hdchain.h:13
UniValue dumpwallet(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:629
Server is in safe mode, and command is not allowed in safe mode.
Definition: protocol.h:43
int Height() const
Definition: chain.h:397
UniValue importwallet(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:305
CBlockIndex * Genesis() const
Definition: chain.h:361
vector< unsigned char > ParseHex(const char *psz)
void GetAllReserveKeys(std::set< CKeyID > &setAddress) const
Definition: wallet.cpp:4151
CChain chainActive
Definition: validation.cpp:65
std::string ToString() const
Definition: uint256.cpp:65
Unexpected type was passed as parameter.
Definition: protocol.h:44
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:262
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:581
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:166
std::map< CKeyID, CHDPubKey > mapHdPubKeys
Definition: wallet.h:757
void MarkDirty()
Definition: wallet.cpp:868
bool SetString(const char *psz, unsigned int nVersionBytes=1)
Definition: base58.cpp:171
const std::string CLIENT_DATE
CKey GetKey()
Definition: base58.cpp:314
CTxDestination Get() const
Definition: base58.cpp:260
int ScanForWalletTransactions(CBlockIndex *pindexStart, bool fUpdate=false)
Definition: wallet.cpp:1687
uint256 GetBlockHash() const
Definition: chain.h:218
void ReacceptWalletTransactions()
Definition: wallet.cpp:1728
UniValue dumpprivkey(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:546
const UniValue NullUniValue
Definition: univalue.cpp:78
bool GetKeyID(CKeyID &keyID) const
Definition: base58.cpp:291
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:748
CBlockIndex * Tip() const
Definition: chain.h:366
Definition: pubkey.h:37
Wallet errors.
Definition: protocol.h:69
bool EnsureWalletIsAvailable(bool avoidException)
Definition: rpcwallet.cpp:42
static std::string EncodeDumpTime(int64_t nTime)
Definition: rpcdump.cpp:33
int64_t GetBlockTime() const
Definition: chain.h:223
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:107
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
virtual bool HaveCScript(const CScriptID &hash) const
Definition: keystore.cpp:51
int64_t nTimeFirstKey
Definition: wallet.h:754
UniValue dumphdinfo(const UniValue &params, bool fHelp)
Definition: rpcdump.cpp:583
Definition: key.h:35
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
virtual bool HaveWatchOnly(const CScript &dest) const
Definition: keystore.cpp:105
UniValue JSONRPCError(int code, const string &message)
Definition: protocol.cpp:57
const std::string CLIENT_BUILD
size_t size() const
Definition: univalue.h:69
void GetKeyBirthTimes(std::map< CKeyID, int64_t > &mapKeyBirth) const
Definition: wallet.cpp:4273
Definition: key.h:154
std::string get_str() const
Definition: univalue.cpp:310
std::string _(const char *psz)
Definition: util.h:84
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Adds a key to the store, and saves it to disk.
Definition: wallet.cpp:288
void SetKey(const K &key)
Definition: base58.h:142