Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

rpcdump.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2019 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/safemode.h>
9 #include <rpc/server.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/wallet.h>
17 #include <merkleblock.h>
18 #include <core_io.h>
19 
20 #include <wallet/rpcwallet.h>
21 
22 #include <fstream>
23 #include <stdint.h>
24 
25 #include <boost/algorithm/string.hpp>
26 #include <boost/date_time/posix_time/posix_time.hpp>
27 
28 #include <univalue.h>
29 
30 
31 std::string static EncodeDumpTime(int64_t nTime) {
32  return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
33 }
34 
35 int64_t static DecodeDumpTime(const std::string &str) {
36  static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
37  static const std::locale loc(std::locale::classic(),
38  new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
39  std::istringstream iss(str);
40  iss.imbue(loc);
41  boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
42  iss >> ptime;
43  if (ptime.is_not_a_date_time())
44  return 0;
45  return (ptime - epoch).total_seconds();
46 }
47 
48 std::string static EncodeDumpString(const std::string &str) {
49  std::stringstream ret;
50  for (unsigned char c : str) {
51  if (c <= 32 || c >= 128 || c == '%') {
52  ret << '%' << HexStr(&c, &c + 1);
53  } else {
54  ret << c;
55  }
56  }
57  return ret.str();
58 }
59 
60 std::string DecodeDumpString(const std::string &str) {
61  std::stringstream ret;
62  for (unsigned int pos = 0; pos < str.length(); pos++) {
63  unsigned char c = str[pos];
64  if (c == '%' && pos+2 < str.length()) {
65  c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
66  ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
67  pos += 2;
68  }
69  ret << c;
70  }
71  return ret.str();
72 }
73 
75 {
76  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
77  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
78  return NullUniValue;
79  }
80 
81  if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
82  throw std::runtime_error(
83  "importprivkey \"privkey\" ( \"label\" ) ( rescan )\n"
84  "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
85  "\nArguments:\n"
86  "1. \"privkey\" (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, during that time, other rpc calls\n"
90  "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
91  "\nExamples:\n"
92  "\nDump a private key\n"
93  + HelpExampleCli("dumpprivkey", "\"myaddress\"") +
94  "\nImport the private key with rescan\n"
95  + HelpExampleCli("importprivkey", "\"mykey\"") +
96  "\nImport using a label and without rescan\n"
97  + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
98  "\nImport using default blank label and without rescan\n"
99  + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") +
100  "\nAs a JSON-RPC call\n"
101  + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
102  );
103 
104 
105  WalletRescanReserver reserver(pwallet);
106  bool fRescan = true;
107  {
108  LOCK2(cs_main, pwallet->cs_wallet);
109 
110  EnsureWalletIsUnlocked(pwallet);
111 
112  std::string strSecret = request.params[0].get_str();
113  std::string strLabel = "";
114  if (!request.params[1].isNull())
115  strLabel = request.params[1].get_str();
116 
117  // Whether to perform rescan after import
118  if (!request.params[2].isNull())
119  fRescan = request.params[2].get_bool();
120 
121  if (fRescan && fPruneMode)
122  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
123 
124  if (fRescan && !reserver.reserve()) {
125  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
126  }
127 
128  CBitcoinSecret vchSecret;
129  bool fGood = vchSecret.SetString(strSecret);
130 
131  if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
132 
133  CKey key = vchSecret.GetKey();
134  if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
135 
136  CPubKey pubkey = key.GetPubKey();
137  assert(key.VerifyPubKey(pubkey));
138  CKeyID vchAddress = pubkey.GetID();
139  {
140  pwallet->MarkDirty();
141  pwallet->SetAddressBook(vchAddress, strLabel, "receive");
142 
143  // Don't throw error in case a key is already there
144  if (pwallet->HaveKey(vchAddress)) {
145  return NullUniValue;
146  }
147 
148  // whenever a key is imported, we need to scan the whole chain
149  pwallet->UpdateTimeFirstKey(1);
150  pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1;
151 
152  if (!pwallet->AddKeyPubKey(key, pubkey)) {
153  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
154  }
155  }
156  }
157  if (fRescan) {
158  pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
159  }
160  return NullUniValue;
161 }
162 
164 {
165  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
166  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
167  return NullUniValue;
168  }
169 
170  if (request.fHelp || request.params.size() > 0)
171  throw std::runtime_error(
172  "abortrescan\n"
173  "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
174  "\nExamples:\n"
175  "\nImport a private key\n"
176  + HelpExampleCli("importprivkey", "\"mykey\"") +
177  "\nAbort the running wallet rescan\n"
178  + HelpExampleCli("abortrescan", "") +
179  "\nAs a JSON-RPC call\n"
180  + HelpExampleRpc("abortrescan", "")
181  );
182 
183  ObserveSafeMode();
184  if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
185  pwallet->AbortRescan();
186  return true;
187 }
188 
189 void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
190 void ImportScript(CWallet * const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
191 {
192  if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
193  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
194  }
195 
196  pwallet->MarkDirty();
197 
198  if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, 0 /* nCreateTime */)) {
199  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
200  }
201 
202  if (isRedeemScript) {
203  if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
204  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
205  }
206  ImportAddress(pwallet, CScriptID(script), strLabel);
207  } else {
208  CTxDestination destination;
209  if (ExtractDestination(script, destination)) {
210  pwallet->SetAddressBook(destination, strLabel, "receive");
211  }
212  }
213 }
214 
215 void ImportAddress(CWallet * const pwallet, const CTxDestination& dest, const std::string& strLabel)
216 {
217  CScript script = GetScriptForDestination(dest);
218  ImportScript(pwallet, script, strLabel, false);
219  // add to address book or update label
220  if (IsValidDestination(dest))
221  pwallet->SetAddressBook(dest, strLabel, "receive");
222 }
223 
225 {
226  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
227  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
228  return NullUniValue;
229  }
230 
231  if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
232  throw std::runtime_error(
233  "importaddress \"address\" ( \"label\" rescan p2sh )\n"
234  "\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
235  "\nArguments:\n"
236  "1. \"script\" (string, required) The hex-encoded script (or address)\n"
237  "2. \"label\" (string, optional, default=\"\") An optional label\n"
238  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
239  "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
240  "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
241  "may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
242  "If you have the full public key, you should call importpubkey instead of this.\n"
243  "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
244  "as change, and not show up in many RPCs.\n"
245  "\nExamples:\n"
246  "\nImport a script with rescan\n"
247  + HelpExampleCli("importaddress", "\"myscript\"") +
248  "\nImport using a label without rescan\n"
249  + HelpExampleCli("importaddress", "\"myscript\" \"testing\" false") +
250  "\nAs a JSON-RPC call\n"
251  + HelpExampleRpc("importaddress", "\"myscript\", \"testing\", false")
252  );
253 
254 
255  std::string strLabel = "";
256  if (!request.params[1].isNull())
257  strLabel = request.params[1].get_str();
258 
259  // Whether to perform rescan after import
260  bool fRescan = true;
261  if (!request.params[2].isNull())
262  fRescan = request.params[2].get_bool();
263 
264  if (fRescan && fPruneMode)
265  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
266 
267  WalletRescanReserver reserver(pwallet);
268  if (fRescan && !reserver.reserve()) {
269  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
270  }
271 
272  // Whether to import a p2sh version, too
273  bool fP2SH = false;
274  if (!request.params[3].isNull())
275  fP2SH = request.params[3].get_bool();
276 
277  {
278  LOCK2(cs_main, pwallet->cs_wallet);
279 
280  CTxDestination dest = DecodeDestination(request.params[0].get_str());
281  if (IsValidDestination(dest)) {
282  if (fP2SH) {
283  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
284  }
285  ImportAddress(pwallet, dest, strLabel);
286  } else if (IsHex(request.params[0].get_str())) {
287  std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
288  ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
289  } else {
290  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address or script");
291  }
292  }
293  if (fRescan)
294  {
295  pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
296  pwallet->ReacceptWalletTransactions();
297  }
298 
299  return NullUniValue;
300 }
301 
303 {
304  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
305  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
306  return NullUniValue;
307  }
308 
309  if (request.fHelp || request.params.size() != 2)
310  throw std::runtime_error(
311  "importprunedfunds\n"
312  "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n"
313  "\nArguments:\n"
314  "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n"
315  "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n"
316  );
317 
319  if (!DecodeHexTx(tx, request.params[0].get_str()))
320  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
321  uint256 hashTx = tx.GetHash();
322  CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
323 
324  CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
325  CMerkleBlock merkleBlock;
326  ssMB >> merkleBlock;
327 
328  //Search partial merkle tree in proof for our transaction and index in valid block
329  std::vector<uint256> vMatch;
330  std::vector<unsigned int> vIndex;
331  unsigned int txnIndex = 0;
332  if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
333 
334  LOCK(cs_main);
335 
336  if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
337  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
338 
339  std::vector<uint256>::const_iterator it;
340  if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) {
341  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction given doesn't exist in proof");
342  }
343 
344  txnIndex = vIndex[it - vMatch.begin()];
345  }
346  else {
347  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Something wrong with merkleblock");
348  }
349 
350  wtx.nIndex = txnIndex;
351  wtx.hashBlock = merkleBlock.header.GetHash();
352 
353  LOCK2(cs_main, pwallet->cs_wallet);
354 
355  if (pwallet->IsMine(*wtx.tx)) {
356  pwallet->AddToWallet(wtx, false);
357  return NullUniValue;
358  }
359 
360  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
361 }
362 
364 {
365  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
366  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
367  return NullUniValue;
368  }
369 
370  if (request.fHelp || request.params.size() != 1)
371  throw std::runtime_error(
372  "removeprunedfunds \"txid\"\n"
373  "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n"
374  "\nArguments:\n"
375  "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
376  "\nExamples:\n"
377  + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
378  "\nAs a JSON-RPC call\n"
379  + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
380  );
381 
382  LOCK2(cs_main, pwallet->cs_wallet);
383 
384  uint256 hash;
385  hash.SetHex(request.params[0].get_str());
386  std::vector<uint256> vHash;
387  vHash.push_back(hash);
388  std::vector<uint256> vHashOut;
389 
390  if (pwallet->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
391  throw JSONRPCError(RPC_WALLET_ERROR, "Could not properly delete the transaction.");
392  }
393 
394  if(vHashOut.empty()) {
395  throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction does not exist in wallet.");
396  }
397 
398  return NullUniValue;
399 }
400 
402 {
403  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
404  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
405  return NullUniValue;
406  }
407 
408  if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
409  throw std::runtime_error(
410  "importpubkey \"pubkey\" ( \"label\" rescan )\n"
411  "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
412  "\nArguments:\n"
413  "1. \"pubkey\" (string, required) The hex-encoded public key\n"
414  "2. \"label\" (string, optional, default=\"\") An optional label\n"
415  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
416  "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
417  "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
418  "\nExamples:\n"
419  "\nImport a public key with rescan\n"
420  + HelpExampleCli("importpubkey", "\"mypubkey\"") +
421  "\nImport using a label without rescan\n"
422  + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
423  "\nAs a JSON-RPC call\n"
424  + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
425  );
426 
427 
428  std::string strLabel = "";
429  if (!request.params[1].isNull())
430  strLabel = request.params[1].get_str();
431 
432  // Whether to perform rescan after import
433  bool fRescan = true;
434  if (!request.params[2].isNull())
435  fRescan = request.params[2].get_bool();
436 
437  if (fRescan && fPruneMode)
438  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
439 
440  WalletRescanReserver reserver(pwallet);
441  if (fRescan && !reserver.reserve()) {
442  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
443  }
444 
445  if (!IsHex(request.params[0].get_str()))
446  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
447  std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
448  CPubKey pubKey(data.begin(), data.end());
449  if (!pubKey.IsFullyValid())
450  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
451 
452  {
453  LOCK2(cs_main, pwallet->cs_wallet);
454 
455  ImportAddress(pwallet, pubKey.GetID(), strLabel);
456  ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
457  }
458  if (fRescan)
459  {
460  pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
461  pwallet->ReacceptWalletTransactions();
462  }
463 
464  return NullUniValue;
465 }
466 
467 
469 {
470  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
471  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
472  return NullUniValue;
473  }
474 
475  if (request.fHelp || request.params.size() != 1)
476  throw std::runtime_error(
477  "importwallet \"filename\"\n"
478  "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
479  "\nArguments:\n"
480  "1. \"filename\" (string, required) The wallet file\n"
481  "\nExamples:\n"
482  "\nDump the wallet\n"
483  + HelpExampleCli("dumpwallet", "\"test\"") +
484  "\nImport the wallet\n"
485  + HelpExampleCli("importwallet", "\"test\"") +
486  "\nImport using the json rpc call\n"
487  + HelpExampleRpc("importwallet", "\"test\"")
488  );
489 
490  if (fPruneMode)
491  throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
492 
493  WalletRescanReserver reserver(pwallet);
494  if (!reserver.reserve()) {
495  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
496  }
497 
498  int64_t nTimeBegin = 0;
499  bool fGood = true;
500  {
501  LOCK2(cs_main, pwallet->cs_wallet);
502 
503  EnsureWalletIsUnlocked(pwallet);
504 
505  std::ifstream file;
506  file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate);
507  if (!file.is_open()) {
508  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
509  }
510  nTimeBegin = chainActive.Tip()->GetBlockTime();
511 
512  int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
513  file.seekg(0, file.beg);
514 
515  pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
516  while (file.good()) {
517  pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
518  std::string line;
519  std::getline(file, line);
520  if (line.empty() || line[0] == '#')
521  continue;
522 
523  std::vector<std::string> vstr;
524  boost::split(vstr, line, boost::is_any_of(" "));
525  if (vstr.size() < 2)
526  continue;
527  CBitcoinSecret vchSecret;
528  if (vchSecret.SetString(vstr[0])) {
529  CKey key = vchSecret.GetKey();
530  CPubKey pubkey = key.GetPubKey();
531  assert(key.VerifyPubKey(pubkey));
532  CKeyID keyid = pubkey.GetID();
533  if (pwallet->HaveKey(keyid)) {
534  LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
535  continue;
536  }
537  int64_t nTime = DecodeDumpTime(vstr[1]);
538  std::string strLabel;
539  bool fLabel = true;
540  for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
541  if (boost::algorithm::starts_with(vstr[nStr], "#"))
542  break;
543  if (vstr[nStr] == "change=1")
544  fLabel = false;
545  if (vstr[nStr] == "reserve=1")
546  fLabel = false;
547  if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
548  strLabel = DecodeDumpString(vstr[nStr].substr(6));
549  fLabel = true;
550  }
551  }
552  LogPrintf("Importing %s...\n", EncodeDestination(keyid));
553  if (!pwallet->AddKeyPubKey(key, pubkey)) {
554  fGood = false;
555  continue;
556  }
557  pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
558  if (fLabel)
559  pwallet->SetAddressBook(keyid, strLabel, "receive");
560  nTimeBegin = std::min(nTimeBegin, nTime);
561  } else if(IsHex(vstr[0])) {
562  std::vector<unsigned char> vData(ParseHex(vstr[0]));
563  CScript script = CScript(vData.begin(), vData.end());
564  if (pwallet->HaveCScript(script)) {
565  LogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
566  continue;
567  }
568  if(!pwallet->AddCScript(script)) {
569  LogPrintf("Error importing script %s\n", vstr[0]);
570  fGood = false;
571  continue;
572  }
573  int64_t birth_time = DecodeDumpTime(vstr[1]);
574  if (birth_time > 0) {
575  pwallet->m_script_metadata[CScriptID(script)].nCreateTime = birth_time;
576  nTimeBegin = std::min(nTimeBegin, birth_time);
577  }
578  }
579  }
580  file.close();
581  pwallet->ShowProgress("", 100); // hide progress dialog in GUI
582  pwallet->UpdateTimeFirstKey(nTimeBegin);
583  }
584  pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */);
585  pwallet->MarkDirty();
586 
587  if (!fGood)
588  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys/scripts to wallet");
589 
590  return NullUniValue;
591 }
592 
594 {
595  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
596  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
597  return NullUniValue;
598 
599  if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
600  throw std::runtime_error(
601  "importelectrumwallet \"filename\" index\n"
602  "\nImports keys from an Electrum wallet export file (.csv or .json)\n"
603  "\nArguments:\n"
604  "1. \"filename\" (string, required) The Electrum wallet export file, should be in csv or json format\n"
605  "2. index (numeric, optional, default=0) Rescan the wallet for transactions starting from this block index\n"
606  "\nExamples:\n"
607  "\nImport the wallet\n"
608  + HelpExampleCli("importelectrumwallet", "\"test.csv\"")
609  + HelpExampleCli("importelectrumwallet", "\"test.json\"") +
610  "\nImport using the json rpc call\n"
611  + HelpExampleRpc("importelectrumwallet", "\"test.csv\"")
612  + HelpExampleRpc("importelectrumwallet", "\"test.json\"")
613  );
614 
615  if (fPruneMode)
616  throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
617 
618  LOCK2(cs_main, pwallet->cs_wallet);
619 
620  EnsureWalletIsUnlocked(pwallet);
621 
622  std::ifstream file;
623  std::string strFileName = request.params[0].get_str();
624  size_t nDotPos = strFileName.find_last_of(".");
625  if(nDotPos == std::string::npos)
626  throw JSONRPCError(RPC_INVALID_PARAMETER, "File has no extension, should be .json or .csv");
627 
628  std::string strFileExt = strFileName.substr(nDotPos+1);
629  if(strFileExt != "json" && strFileExt != "csv")
630  throw JSONRPCError(RPC_INVALID_PARAMETER, "File has wrong extension, should be .json or .csv");
631 
632  file.open(strFileName.c_str(), std::ios::in | std::ios::ate);
633  if (!file.is_open())
634  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open Electrum wallet export file");
635 
636  bool fGood = true;
637 
638  int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
639  file.seekg(0, file.beg);
640 
641  pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
642 
643  if(strFileExt == "csv") {
644  while (file.good()) {
645  pwallet->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
646  std::string line;
647  std::getline(file, line);
648  if (line.empty() || line == "address,private_key")
649  continue;
650  std::vector<std::string> vstr;
651  boost::split(vstr, line, boost::is_any_of(","));
652  if (vstr.size() < 2)
653  continue;
654  CBitcoinSecret vchSecret;
655  if (!vchSecret.SetString(vstr[1]))
656  continue;
657  CKey key = vchSecret.GetKey();
658  CPubKey pubkey = key.GetPubKey();
659  assert(key.VerifyPubKey(pubkey));
660  CKeyID keyid = pubkey.GetID();
661  if (pwallet->HaveKey(keyid)) {
662  LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
663  continue;
664  }
665  LogPrintf("Importing %s...\n", EncodeDestination(keyid));
666  if (!pwallet->AddKeyPubKey(key, pubkey)) {
667  fGood = false;
668  continue;
669  }
670  }
671  } else {
672  // json
673  char* buffer = new char [nFilesize];
674  file.read(buffer, nFilesize);
675  UniValue data(UniValue::VOBJ);
676  if(!data.read(buffer))
677  throw JSONRPCError(RPC_TYPE_ERROR, "Cannot parse Electrum wallet export file");
678  delete[] buffer;
679 
680  std::vector<std::string> vKeys = data.getKeys();
681 
682  for (size_t i = 0; i < data.size(); i++) {
683  pwallet->ShowProgress("", std::max(1, std::min(99, int(i*100/data.size()))));
684  if(!data[vKeys[i]].isStr())
685  continue;
686  CBitcoinSecret vchSecret;
687  if (!vchSecret.SetString(data[vKeys[i]].get_str()))
688  continue;
689  CKey key = vchSecret.GetKey();
690  CPubKey pubkey = key.GetPubKey();
691  assert(key.VerifyPubKey(pubkey));
692  CKeyID keyid = pubkey.GetID();
693  if (pwallet->HaveKey(keyid)) {
694  LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
695  continue;
696  }
697  LogPrintf("Importing %s...\n", EncodeDestination(keyid));
698  if (!pwallet->AddKeyPubKey(key, pubkey)) {
699  fGood = false;
700  continue;
701  }
702  }
703  }
704  file.close();
705  pwallet->ShowProgress("", 100); // hide progress dialog in GUI
706 
707  // Whether to perform rescan after import
708  int nStartHeight = 0;
709  if (!request.params[1].isNull())
710  nStartHeight = request.params[1].get_int();
711  if (chainActive.Height() < nStartHeight)
712  nStartHeight = chainActive.Height();
713 
714  // Assume that electrum wallet was created at that block
715  int nTimeBegin = chainActive[nStartHeight]->GetBlockTime();
716  pwallet->UpdateTimeFirstKey(nTimeBegin);
717 
718  LogPrintf("Rescanning %i blocks\n", chainActive.Height() - nStartHeight + 1);
719  WalletRescanReserver reserver(pwallet);
720  if (!reserver.reserve()) {
721  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
722  }
723  pwallet->ScanForWalletTransactions(chainActive[nStartHeight], nullptr, reserver, true);
724 
725  if (!fGood)
726  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
727 
728  return NullUniValue;
729 }
730 
732 {
733  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
734  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
735  return NullUniValue;
736  }
737 
738  if (request.fHelp || request.params.size() != 1)
739  throw std::runtime_error(
740  "dumpprivkey \"address\"\n"
741  "\nReveals the private key corresponding to 'address'.\n"
742  "Then the importprivkey can be used with this output\n"
743  "\nArguments:\n"
744  "1. \"address\" (string, required) The dash address for the private key\n"
745  "\nResult:\n"
746  "\"key\" (string) The private key\n"
747  "\nExamples:\n"
748  + HelpExampleCli("dumpprivkey", "\"myaddress\"")
749  + HelpExampleCli("importprivkey", "\"mykey\"")
750  + HelpExampleRpc("dumpprivkey", "\"myaddress\"")
751  );
752 
753  LOCK2(cs_main, pwallet->cs_wallet);
754 
755  EnsureWalletIsUnlocked(pwallet);
756 
757  std::string strAddress = request.params[0].get_str();
758  CTxDestination dest = DecodeDestination(strAddress);
759  if (!IsValidDestination(dest)) {
760  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
761  }
762  const CKeyID *keyID = boost::get<CKeyID>(&dest);
763  if (!keyID) {
764  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
765  }
766  CKey vchSecret;
767  if (!pwallet->GetKey(*keyID, vchSecret)) {
768  throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
769  }
770  return CBitcoinSecret(vchSecret).ToString();
771 }
772 
774 {
775  CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
776  if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
777  return NullUniValue;
778 
779  if (request.fHelp || request.params.size() != 0)
780  throw std::runtime_error(
781  "dumphdinfo\n"
782  "Returns an object containing sensitive private info about this HD wallet.\n"
783  "\nResult:\n"
784  "{\n"
785  " \"hdseed\": \"seed\", (string) The HD seed (bip32, in hex)\n"
786  " \"mnemonic\": \"words\", (string) The mnemonic for this HD wallet (bip39, english words) \n"
787  " \"mnemonicpassphrase\": \"passphrase\", (string) The mnemonic passphrase for this HD wallet (bip39)\n"
788  "}\n"
789  "\nExamples:\n"
790  + HelpExampleCli("dumphdinfo", "")
791  + HelpExampleRpc("dumphdinfo", "")
792  );
793 
794  LOCK(pwallet->cs_wallet);
795 
796  EnsureWalletIsUnlocked(pwallet);
797 
798  CHDChain hdChainCurrent;
799  if (!pwallet->GetHDChain(hdChainCurrent))
800  throw JSONRPCError(RPC_WALLET_ERROR, "This wallet is not a HD wallet.");
801 
802  if (!pwallet->GetDecryptedHDChain(hdChainCurrent))
803  throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD seed");
804 
805  SecureString ssMnemonic;
806  SecureString ssMnemonicPassphrase;
807  hdChainCurrent.GetMnemonic(ssMnemonic, ssMnemonicPassphrase);
808 
810  obj.push_back(Pair("hdseed", HexStr(hdChainCurrent.GetSeed())));
811  obj.push_back(Pair("mnemonic", ssMnemonic.c_str()));
812  obj.push_back(Pair("mnemonicpassphrase", ssMnemonicPassphrase.c_str()));
813 
814  return obj;
815 }
816 
818 {
819  CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
820  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
821  return NullUniValue;
822  }
823 
824  if (request.fHelp || request.params.size() != 1)
825  throw std::runtime_error(
826  "dumpwallet \"filename\"\n"
827  "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
828  "Imported scripts are included in the dumpfile too, their corresponding addresses will be added automatically by importwallet.\n"
829  "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n"
830  "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n"
831  "\nArguments:\n"
832  "1. \"filename\" (string, required) The filename\n"
833  "\nExamples:\n"
834  + HelpExampleCli("dumpwallet", "\"test\"")
835  + HelpExampleRpc("dumpwallet", "\"test\"")
836  );
837 
838  LOCK2(cs_main, pwallet->cs_wallet);
839 
840  EnsureWalletIsUnlocked(pwallet);
841 
842  boost::filesystem::path filepath = request.params[0].get_str();
843  filepath = boost::filesystem::absolute(filepath);
844 
845  /* Prevent arbitrary files from being overwritten. There have been reports
846  * that users have overwritten wallet files this way:
847  * https://github.com/bitcoin/bitcoin/issues/9934
848  * It may also avoid other security issues.
849  */
850  if (boost::filesystem::exists(filepath)) {
851  throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
852  }
853 
854  std::ofstream file;
855  file.open(filepath.string().c_str());
856  if (!file.is_open())
857  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
858 
859  std::map<CTxDestination, int64_t> mapKeyBirth;
860  const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys();
861  pwallet->GetKeyBirthTimes(mapKeyBirth);
862 
863  std::set<CScriptID> scripts = pwallet->GetCScripts();
864  // TODO: include scripts in GetKeyBirthTimes() output instead of separate
865 
866  // sort time/key pairs
867  std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
868  for (const auto& entry : mapKeyBirth) {
869  if (const CKeyID* keyID = boost::get<CKeyID>(&entry.first)) { // set and test
870  vKeyBirth.push_back(std::make_pair(entry.second, *keyID));
871  }
872  }
873  mapKeyBirth.clear();
874  std::sort(vKeyBirth.begin(), vKeyBirth.end());
875 
876  // produce output
877  file << strprintf("# Wallet dump created by Dash Core %s\n", CLIENT_BUILD);
878  file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
879  file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
880  file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
881  file << "\n";
882 
884  obj.push_back(Pair("dashcoreversion", CLIENT_BUILD));
885  obj.push_back(Pair("lastblockheight", chainActive.Height()));
886  obj.push_back(Pair("lastblockhash", chainActive.Tip()->GetBlockHash().ToString()));
887  obj.push_back(Pair("lastblocktime", EncodeDumpTime(chainActive.Tip()->GetBlockTime())));
888 
889  // add the base58check encoded extended master if the wallet uses HD
890  CHDChain hdChainCurrent;
891  if (pwallet->GetHDChain(hdChainCurrent))
892  {
893 
894  if (!pwallet->GetDecryptedHDChain(hdChainCurrent))
895  throw JSONRPCError(RPC_INTERNAL_ERROR, "Cannot decrypt HD chain");
896 
897  SecureString ssMnemonic;
898  SecureString ssMnemonicPassphrase;
899  hdChainCurrent.GetMnemonic(ssMnemonic, ssMnemonicPassphrase);
900  file << "# mnemonic: " << ssMnemonic << "\n";
901  file << "# mnemonic passphrase: " << ssMnemonicPassphrase << "\n\n";
902 
903  SecureVector vchSeed = hdChainCurrent.GetSeed();
904  file << "# HD seed: " << HexStr(vchSeed) << "\n\n";
905 
906  CExtKey masterKey;
907  masterKey.SetMaster(&vchSeed[0], vchSeed.size());
908 
909  CBitcoinExtKey b58extkey;
910  b58extkey.SetKey(masterKey);
911 
912  file << "# extended private masterkey: " << b58extkey.ToString() << "\n";
913 
914  CExtPubKey masterPubkey;
915  masterPubkey = masterKey.Neuter();
916 
917  CBitcoinExtPubKey b58extpubkey;
918  b58extpubkey.SetKey(masterPubkey);
919  file << "# extended public masterkey: " << b58extpubkey.ToString() << "\n\n";
920 
921  for (size_t i = 0; i < hdChainCurrent.CountAccounts(); ++i)
922  {
923  CHDAccount acc;
924  if(hdChainCurrent.GetAccount(i, acc)) {
925  file << "# external chain counter: " << acc.nExternalChainCounter << "\n";
926  file << "# internal chain counter: " << acc.nInternalChainCounter << "\n\n";
927  } else {
928  file << "# WARNING: ACCOUNT " << i << " IS MISSING!" << "\n\n";
929  }
930  }
931  obj.push_back(Pair("hdaccounts", int(hdChainCurrent.CountAccounts())));
932  }
933 
934  for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
935  const CKeyID &keyid = it->second;
936  std::string strTime = EncodeDumpTime(it->first);
937  std::string strAddr = EncodeDestination(keyid);
938  CKey key;
939  if (pwallet->GetKey(keyid, key)) {
940  file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
941  if (pwallet->mapAddressBook.count(keyid)) {
942  file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook[keyid].name));
943  } else if (mapKeyPool.count(keyid)) {
944  file << "reserve=1";
945  } else {
946  file << "change=1";
947  }
948  file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapHdPubKeys.count(keyid) ? " hdkeypath="+pwallet->mapHdPubKeys[keyid].GetKeyPath() : ""));
949  }
950  }
951  file << "\n";
952  for (const CScriptID &scriptid : scripts) {
953  CScript script;
954  std::string create_time = "0";
955  std::string address = EncodeDestination(scriptid);
956  // get birth times for scripts with metadata
957  auto it = pwallet->m_script_metadata.find(scriptid);
958  if (it != pwallet->m_script_metadata.end()) {
959  create_time = EncodeDumpTime(it->second.nCreateTime);
960  }
961  if(pwallet->GetCScript(scriptid, script)) {
962  file << strprintf("%s %s script=1", HexStr(script.begin(), script.end()), create_time);
963  file << strprintf(" # addr=%s\n", address);
964  }
965  }
966  file << "\n";
967  file << "# End of dump\n";
968  file.close();
969 
970  std::string strWarning = strprintf(_("%s file contains all private keys from this wallet. Do not share it with anyone!"), request.params[0].get_str().c_str());
971  obj.push_back(Pair("keys", int(vKeyBirth.size())));
972  obj.push_back(Pair("file", request.params[0].get_str().c_str()));
973  obj.push_back(Pair("warning", strWarning));
974 
975  return obj;
976 }
977 
978 
979 UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
980 {
981  try {
982  bool success = false;
983 
984  // Required fields.
985  const UniValue& scriptPubKey = data["scriptPubKey"];
986 
987  // Should have script or JSON with "address".
988  if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) {
989  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey");
990  }
991 
992  // Optional fields.
993  const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
994  const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
995  const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
996  const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
997  const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
998  const std::string& label = data.exists("label") && !internal ? data["label"].get_str() : "";
999 
1000  bool isScript = scriptPubKey.getType() == UniValue::VSTR;
1001  bool isP2SH = strRedeemScript.length() > 0;
1002  const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
1003 
1004  // Parse the output.
1005  CScript script;
1006  CTxDestination dest;
1007 
1008  if (!isScript) {
1009  dest = DecodeDestination(output);
1010  if (!IsValidDestination(dest)) {
1011  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
1012  }
1013  script = GetScriptForDestination(dest);
1014  } else {
1015  if (!IsHex(output)) {
1016  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey");
1017  }
1018 
1019  std::vector<unsigned char> vData(ParseHex(output));
1020  script = CScript(vData.begin(), vData.end());
1021  }
1022 
1023  // Watchonly and private keys
1024  if (watchOnly && keys.size()) {
1025  throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys");
1026  }
1027 
1028  // Internal + Label
1029  if (internal && data.exists("label")) {
1030  throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label");
1031  }
1032 
1033  // Not having Internal + Script
1034  if (!internal && isScript) {
1035  throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set for hex scriptPubKey");
1036  }
1037 
1038  // Keys / PubKeys size check.
1039  if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey
1040  throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address");
1041  }
1042 
1043  // Invalid P2SH redeemScript
1044  if (isP2SH && !IsHex(strRedeemScript)) {
1045  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script");
1046  }
1047 
1048  // Process. //
1049 
1050  // P2SH
1051  if (isP2SH) {
1052  // Import redeem script.
1053  std::vector<unsigned char> vData(ParseHex(strRedeemScript));
1054  CScript redeemScript = CScript(vData.begin(), vData.end());
1055 
1056  // Invalid P2SH address
1057  if (!script.IsPayToScriptHash()) {
1058  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
1059  }
1060 
1061  pwallet->MarkDirty();
1062 
1063  if (!pwallet->AddWatchOnly(redeemScript, timestamp)) {
1064  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
1065  }
1066 
1067  if (!pwallet->HaveCScript(redeemScript) && !pwallet->AddCScript(redeemScript)) {
1068  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
1069  }
1070 
1071  CTxDestination redeem_dest = CScriptID(redeemScript);
1072  CScript redeemDestination = GetScriptForDestination(redeem_dest);
1073 
1074  if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
1075  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
1076  }
1077 
1078  pwallet->MarkDirty();
1079 
1080  if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) {
1081  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
1082  }
1083 
1084  // add to address book or update label
1085  if (IsValidDestination(dest)) {
1086  pwallet->SetAddressBook(dest, label, "receive");
1087  }
1088 
1089  // Import private keys.
1090  if (keys.size()) {
1091  for (size_t i = 0; i < keys.size(); i++) {
1092  const std::string& privkey = keys[i].get_str();
1093 
1094  CBitcoinSecret vchSecret;
1095  bool fGood = vchSecret.SetString(privkey);
1096 
1097  if (!fGood) {
1098  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1099  }
1100 
1101  CKey key = vchSecret.GetKey();
1102 
1103  if (!key.IsValid()) {
1104  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
1105  }
1106 
1107  CPubKey pubkey = key.GetPubKey();
1108  assert(key.VerifyPubKey(pubkey));
1109 
1110  CKeyID vchAddress = pubkey.GetID();
1111  pwallet->MarkDirty();
1112  pwallet->SetAddressBook(vchAddress, label, "receive");
1113 
1114  if (pwallet->HaveKey(vchAddress)) {
1115  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
1116  }
1117 
1118  pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
1119 
1120  if (!pwallet->AddKeyPubKey(key, pubkey)) {
1121  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
1122  }
1123 
1124  pwallet->UpdateTimeFirstKey(timestamp);
1125  }
1126  }
1127 
1128  success = true;
1129  } else {
1130  // Import public keys.
1131  if (pubKeys.size() && keys.size() == 0) {
1132  const std::string& strPubKey = pubKeys[0].get_str();
1133 
1134  if (!IsHex(strPubKey)) {
1135  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
1136  }
1137 
1138  std::vector<unsigned char> vData(ParseHex(strPubKey));
1139  CPubKey pubKey(vData.begin(), vData.end());
1140 
1141  if (!pubKey.IsFullyValid()) {
1142  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
1143  }
1144 
1145  CTxDestination pubkey_dest = pubKey.GetID();
1146 
1147  // Consistency check.
1148  if (!isScript && !(pubkey_dest == dest)) {
1149  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
1150  }
1151 
1152  // Consistency check.
1153  if (isScript) {
1154  CTxDestination destination;
1155 
1156  if (ExtractDestination(script, destination)) {
1157  if (!(destination == pubkey_dest)) {
1158  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
1159  }
1160  }
1161  }
1162 
1163  CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
1164 
1165  if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
1166  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
1167  }
1168 
1169  pwallet->MarkDirty();
1170 
1171  if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
1172  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
1173  }
1174 
1175  // add to address book or update label
1176  if (IsValidDestination(pubkey_dest)) {
1177  pwallet->SetAddressBook(pubkey_dest, label, "receive");
1178  }
1179 
1180  // TODO Is this necessary?
1181  CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey);
1182 
1183  if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
1184  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
1185  }
1186 
1187  pwallet->MarkDirty();
1188 
1189  if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
1190  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
1191  }
1192 
1193  success = true;
1194  }
1195 
1196  // Import private keys.
1197  if (keys.size()) {
1198  const std::string& strPrivkey = keys[0].get_str();
1199 
1200  // Checks.
1201  CBitcoinSecret vchSecret;
1202  bool fGood = vchSecret.SetString(strPrivkey);
1203 
1204  if (!fGood) {
1205  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1206  }
1207 
1208  CKey key = vchSecret.GetKey();
1209  if (!key.IsValid()) {
1210  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
1211  }
1212 
1213  CPubKey pubKey = key.GetPubKey();
1214  assert(key.VerifyPubKey(pubKey));
1215 
1216  CTxDestination pubkey_dest = pubKey.GetID();
1217 
1218  // Consistency check.
1219  if (!isScript && !(pubkey_dest == dest)) {
1220  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
1221  }
1222 
1223  // Consistency check.
1224  if (isScript) {
1225  CTxDestination destination;
1226 
1227  if (ExtractDestination(script, destination)) {
1228  if (!(destination == pubkey_dest)) {
1229  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
1230  }
1231  }
1232  }
1233 
1234  CKeyID vchAddress = pubKey.GetID();
1235  pwallet->MarkDirty();
1236  pwallet->SetAddressBook(vchAddress, label, "receive");
1237 
1238  if (pwallet->HaveKey(vchAddress)) {
1239  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
1240  }
1241 
1242  pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
1243 
1244  if (!pwallet->AddKeyPubKey(key, pubKey)) {
1245  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
1246  }
1247 
1248  pwallet->UpdateTimeFirstKey(timestamp);
1249 
1250  success = true;
1251  }
1252 
1253  // Import scriptPubKey only.
1254  if (pubKeys.size() == 0 && keys.size() == 0) {
1255  if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
1256  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
1257  }
1258 
1259  pwallet->MarkDirty();
1260 
1261  if (!pwallet->AddWatchOnly(script, timestamp)) {
1262  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
1263  }
1264 
1265  if (scriptPubKey.getType() == UniValue::VOBJ) {
1266  // add to address book or update label
1267  if (IsValidDestination(dest)) {
1268  pwallet->SetAddressBook(dest, label, "receive");
1269  }
1270  }
1271 
1272  success = true;
1273  }
1274  }
1275 
1276  UniValue result = UniValue(UniValue::VOBJ);
1277  result.pushKV("success", UniValue(success));
1278  return result;
1279  } catch (const UniValue& e) {
1280  UniValue result = UniValue(UniValue::VOBJ);
1281  result.pushKV("success", UniValue(false));
1282  result.pushKV("error", e);
1283  return result;
1284  } catch (...) {
1285  UniValue result = UniValue(UniValue::VOBJ);
1286  result.pushKV("success", UniValue(false));
1287  result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields"));
1288  return result;
1289  }
1290 }
1291 
1292 int64_t GetImportTimestamp(const UniValue& data, int64_t now)
1293 {
1294  if (data.exists("timestamp")) {
1295  const UniValue& timestamp = data["timestamp"];
1296  if (timestamp.isNum()) {
1297  return timestamp.get_int64();
1298  } else if (timestamp.isStr() && timestamp.get_str() == "now") {
1299  return now;
1300  }
1301  throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected number or \"now\" timestamp value for key. got type %s", uvTypeName(timestamp.type())));
1302  }
1303  throw JSONRPCError(RPC_TYPE_ERROR, "Missing required timestamp field for key");
1304 }
1305 
1307 {
1308  CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest);
1309  if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
1310  return NullUniValue;
1311  }
1312 
1313  // clang-format off
1314  if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
1315  throw std::runtime_error(
1316  "importmulti \"requests\" ( \"options\" )\n\n"
1317  "Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options). Requires a new wallet backup.\n\n"
1318  "Arguments:\n"
1319  "1. requests (array, required) Data to be imported\n"
1320  " [ (array of json objects)\n"
1321  " {\n"
1322  " \"scriptPubKey\": \"<script>\" | { \"address\":\"<address>\" }, (string / json, required) Type of scriptPubKey (string for script, json for address)\n"
1323  " \"timestamp\": timestamp | \"now\" , (integer / string, required) Creation time of the key in seconds since epoch (Jan 1 1970 GMT),\n"
1324  " or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
1325  " key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
1326  " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
1327  " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
1328  " creation time of all keys being imported by the importmulti call will be scanned.\n"
1329  " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH address or a P2SH scriptPubKey\n"
1330  " \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n"
1331  " \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n"
1332  " \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n"
1333  " \"watchonly\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be considered watched even when they're not spendable, only allowed if keys are empty\n"
1334  " \"label\": <label> , (string, optional, default: '') Label to assign to the address (aka account name, for now), only allowed with internal=false\n"
1335  " }\n"
1336  " ,...\n"
1337  " ]\n"
1338  "2. options (json, optional)\n"
1339  " {\n"
1340  " \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n"
1341  " }\n"
1342  "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
1343  "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n"
1344  "\nExamples:\n" +
1345  HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
1346  "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1347  HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") +
1348 
1349  "\nResponse is an array with the same size as the input that has the execution result :\n"
1350  " [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
1351 
1352  // clang-format on
1353 
1354  RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
1355 
1356  const UniValue& requests = mainRequest.params[0];
1357 
1358  //Default options
1359  bool fRescan = true;
1360 
1361  if (!mainRequest.params[1].isNull()) {
1362  const UniValue& options = mainRequest.params[1];
1363 
1364  if (options.exists("rescan")) {
1365  fRescan = options["rescan"].get_bool();
1366  }
1367  }
1368 
1369  WalletRescanReserver reserver(pwallet);
1370  if (fRescan && !reserver.reserve()) {
1371  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
1372  }
1373 
1374  int64_t now = 0;
1375  bool fRunScan = false;
1376  int64_t nLowestTimestamp = 0;
1377  UniValue response(UniValue::VARR);
1378  {
1379  LOCK2(cs_main, pwallet->cs_wallet);
1380  EnsureWalletIsUnlocked(pwallet);
1381 
1382  // Verify all timestamps are present before importing any keys.
1383  now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
1384  for (const UniValue& data : requests.getValues()) {
1385  GetImportTimestamp(data, now);
1386  }
1387 
1388  const int64_t minimumTimestamp = 1;
1389 
1390  if (fRescan && chainActive.Tip()) {
1391  nLowestTimestamp = chainActive.Tip()->GetBlockTime();
1392  } else {
1393  fRescan = false;
1394  }
1395 
1396  for (const UniValue& data : requests.getValues()) {
1397  const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
1398  const UniValue result = ProcessImport(pwallet, data, timestamp);
1399  response.push_back(result);
1400 
1401  if (!fRescan) {
1402  continue;
1403  }
1404 
1405  // If at least one request was successful then allow rescan.
1406  if (result["success"].get_bool()) {
1407  fRunScan = true;
1408  }
1409 
1410  // Get the lowest timestamp.
1411  if (timestamp < nLowestTimestamp) {
1412  nLowestTimestamp = timestamp;
1413  }
1414  }
1415  }
1416  if (fRescan && fRunScan && requests.size()) {
1417  int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
1418  pwallet->ReacceptWalletTransactions();
1419 
1420  if (scannedTime > nLowestTimestamp) {
1421  std::vector<UniValue> results = response.getValues();
1422  response.clear();
1423  response.setArray();
1424  size_t i = 0;
1425  for (const UniValue& request : requests.getValues()) {
1426  // If key creation date is within the successfully scanned
1427  // range, or if the import result already has an error set, let
1428  // the result stand unmodified. Otherwise replace the result
1429  // with an error message.
1430  if (scannedTime <= GetImportTimestamp(request, now) || results.at(i).exists("error")) {
1431  response.push_back(results.at(i));
1432  } else {
1433  UniValue result = UniValue(UniValue::VOBJ);
1434  result.pushKV("success", UniValue(false));
1435  result.pushKV(
1436  "error",
1437  JSONRPCError(
1439  strprintf("Rescan failed for key with creation timestamp %d. There was an error reading a "
1440  "block from time %d, which is after or within %d seconds of key creation, and "
1441  "could contain transactions pertaining to the key. As a result, transactions "
1442  "and coins using this key may not appear in the wallet. This error could be "
1443  "caused by pruning or data corruption (see dashd log for details) and could "
1444  "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1445  "and -rescan options).",
1446  GetImportTimestamp(request, now), scannedTime - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW)));
1447  response.push_back(std::move(result));
1448  }
1449  ++i;
1450  }
1451  }
1452  }
1453 
1454  return response;
1455 }
static std::string EncodeDumpString(const std::string &str)
Definition: rpcdump.cpp:48
UniValue dumphdinfo(const JSONRPCRequest &request)
Definition: rpcdump.cpp:773
std::string DecodeDumpString(const std::string &str)
Definition: rpcdump.cpp:60
UniValue abortrescan(const JSONRPCRequest &request)
Definition: rpcdump.cpp:163
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:80
bool fPruneMode
True if we&#39;re running in -prune mode.
Definition: validation.cpp:230
static int64_t DecodeDumpTime(const std::string &str)
Definition: rpcdump.cpp:35
const std::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
int64_t GetBlockTime() const
Definition: chain.h:297
void GetKeyBirthTimes(std::map< CTxDestination, int64_t > &mapKeyBirth) const
Definition: wallet.cpp:4856
bool get_bool() const
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
Definition: wallet.h:1122
UniValue dumpprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:731
CKey GetKey()
Definition: base58.cpp:304
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:906
bool read(const char *raw, size_t len)
CCriticalSection cs_wallet
Definition: wallet.h:836
#define strprintf
Definition: tinyformat.h:1066
bool IsPayToScriptHash() const
Definition: script.cpp:212
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:207
UniValue importmulti(const JSONRPCRequest &mainRequest)
Definition: rpcdump.cpp:1306
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:179
uint32_t nExternalChainCounter
Definition: hdchain.h:13
int nIndex
Definition: wallet.h:218
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:66
BlockMap & mapBlockIndex
Definition: validation.cpp:215
bool HaveCScript(const CScriptID &hash) const override
Definition: keystore.cpp:74
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
Definition: utiltime.cpp:93
std::set< CScriptID > GetCScripts() const override
Definition: keystore.cpp:80
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
Adds a key to the store, and saves it to disk.
Definition: wallet.cpp:405
Definition: key.h:141
void ReacceptWalletTransactions()
Definition: wallet.cpp:2106
bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
Definition: keystore.cpp:90
int Height() const
Return the maximal height in the chain.
Definition: chain.h:484
uint256 hashBlock
Definition: wallet.h:211
CCriticalSection cs_main
Definition: validation.cpp:213
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:281
CTxDestination DecodeDestination(const std::string &str)
Definition: base58.cpp:336
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:57
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:264
UniValue dumpwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:817
const std::string & get_str() const
enum VType getType() const
Definition: univalue.h:65
bool isNum() const
Definition: univalue.h:83
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: server.cpp:583
const UniValue & get_array() const
bool isStr() const
Definition: univalue.h:82
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
int64_t get_int64() const
const std::vector< std::string > & getKeys() const
void SetKey(const K &key)
Definition: base58.h:117
UniValue importelectrumwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:593
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:90
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:149
bool AddWatchOnly(const CScript &dest) override
Private version of AddWatchOnly method which does not accept a timestamp, and which will reset the wa...
Definition: wallet.cpp:490
void RPCTypeCheck(const UniValue &params, const std::list< UniValue::VType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: server.cpp:54
std::map< CScriptID, CKeyMetadata > m_script_metadata
Definition: wallet.h:856
Invalid, missing or duplicate parameter.
Definition: protocol.h:53
bool SetString(const char *pszSecret)
Definition: base58.cpp:319
std::string ToString() const
Definition: base58.cpp:193
uint256 GetBlockHash() const
Definition: chain.h:292
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:4277
iterator end()
Definition: prevector.h:320
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: utiltime.cpp:22
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:346
uint32_t nInternalChainCounter
Definition: hdchain.h:14
void MarkDirty()
Definition: wallet.cpp:1082
#define LOCK2(cs1, cs2)
Definition: sync.h:179
const char * uvTypeName(UniValue::VType t)
Definition: univalue.cpp:221
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
Definition: merkleblock.h:127
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
#define LogPrintf(...)
Definition: util.h:203
CTransactionRef tx
Definition: wallet.h:210
UniValue params
Definition: server.h:42
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
Definition: wallet.cpp:467
#define LOCK(cs)
Definition: sync.h:178
A base58-encoded secret key.
Definition: base58.h:101
bool exists(const std::string &key) const
Definition: univalue.h:76
bool GetKey(const CKeyID &address, CKey &keyOut) const override
GetKey implementation that can derive a HD private key on the fly.
Definition: wallet.cpp:300
void ImportScript(CWallet *const pwallet, const CScript &script, const std::string &strLabel, bool isRedeemScript)
Definition: rpcdump.cpp:190
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:471
std::vector< unsigned char, secure_allocator< unsigned char > > SecureVector
Definition: secure.h:59
UniValue removeprunedfunds(const JSONRPCRequest &request)
Definition: rpcdump.cpp:363
An encapsulated public key.
Definition: pubkey.h:30
virtual bool GetHDChain(CHDChain &hdChainRet) const override
Definition: crypter.cpp:539
bool IsHex(const std::string &str)
Unexpected type was passed as parameter.
Definition: protocol.h:50
void UpdateTimeFirstKey(int64_t nCreateTime)
Update wallet first key creation time.
Definition: wallet.cpp:455
General application defined errors.
Definition: protocol.h:48
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:135
UniValue ProcessImport(CWallet *const pwallet, const UniValue &data, const int64_t timestamp)
Definition: rpcdump.cpp:979
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
Definition: wallet.cpp:4220
int get_int() const
std::string ToString() const
Definition: uint256.cpp:62
Invalid address or key.
Definition: protocol.h:51
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:256
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:578
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:185
bool isNull() const
Definition: univalue.h:78
bool AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose=true)
Definition: wallet.cpp:1094
int64_t GetMedianTimePast() const
Definition: chain.h:309
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1336
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:280
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string strName)
Definition: server.cpp:138
static const int64_t TIMESTAMP_MIN
Definition: wallet.h:78
CBlockIndex * ScanForWalletTransactions(CBlockIndex *pindexStart, CBlockIndex *pindexStop, const WalletRescanReserver &reserver, bool fUpdate=false)
Scan the block chain (starting in pindexStart) for transactions from or to us.
Definition: wallet.cpp:2030
bool fHelp
Definition: server.h:43
int64_t GetImportTimestamp(const UniValue &data, int64_t now)
Definition: rpcdump.cpp:1292
256-bit opaque blob.
Definition: uint256.h:123
bool GetMnemonic(SecureVector &vchMnemonicRet, SecureVector &vchMnemonicPassphraseRet) const
Definition: hdchain.cpp:107
enum VType type() const
Definition: univalue.h:174
SecureVector GetSeed() const
Definition: hdchain.cpp:141
bool setArray()
Definition: univalue.cpp:96
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:66
std::string EncodeDestination(const CTxDestination &dest)
Definition: base58.cpp:329
CExtPubKey Neuter() const
Definition: key.cpp:287
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:389
std::map< CKeyID, CHDPubKey > mapHdPubKeys
Definition: wallet.h:912
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:14
UniValue importpubkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:401
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:453
bool IsScanning()
Definition: wallet.h:979
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:715
const UniValue NullUniValue
Definition: univalue.cpp:15
bool GetAccount(uint32_t nAccountIndex, CHDAccount &hdAccountRet)
Definition: hdchain.cpp:184
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:45
std::map< CKeyID, CKeyMetadata > mapKeyMetadata
Definition: wallet.h:853
UniValue importprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:74
void AbortRescan()
Definition: wallet.h:977
void SetMaster(const unsigned char *seed, unsigned int nSeedLen)
Definition: key.cpp:276
iterator begin()
Definition: prevector.h:318
UniValue importwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:468
void ObserveSafeMode()
Definition: safemode.cpp:7
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:1200
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:22
UniValue importaddress(const JSONRPCRequest &request)
Definition: rpcdump.cpp:224
A mutable version of CTransaction.
Definition: transaction.h:291
Wallet errors.
Definition: protocol.h:77
static std::string EncodeDumpTime(int64_t nTime)
Definition: rpcdump.cpp:31
bool IsAbortingRescan()
Definition: wallet.h:978
void ImportAddress(CWallet *, const CTxDestination &dest, const std::string &strLabel)
Definition: rpcdump.cpp:215
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:54
void clear()
Definition: univalue.cpp:17
size_t size() const
Definition: univalue.h:69
An encapsulated private key.
Definition: key.h:27
bool HaveWatchOnly(const CScript &dest) const override
Definition: keystore.cpp:138
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition: wallet.cpp:1993
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1542
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:217
void SetHex(const char *psz)
Definition: uint256.cpp:27
bool GetDecryptedHDChain(CHDChain &hdChainRet)
Definition: wallet.cpp:1826
const std::string CLIENT_BUILD
static const int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
Definition: chain.h:29
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: ismine.cpp:28
UniValue importprunedfunds(const JSONRPCRequest &request)
Definition: rpcdump.cpp:302
bool HaveKey(const CKeyID &address) const override
HaveKey implementation that also checks the mapHdPubKeys.
Definition: wallet.cpp:328
size_t CountAccounts()
Definition: hdchain.cpp:203
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:92
Error parsing or validating structure in raw format.
Definition: protocol.h:55
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
void EnsureWalletIsUnlocked(CWallet *const pwallet)
Definition: rpcwallet.cpp:83
std::vector< unsigned char > ParseHex(const char *psz)
Released under the MIT license