BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
rpcdump.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2018 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <chain.h>
6 #include <key_io.h>
7 #include <rpc/server.h>
8 #include <validation.h>
9 #include <script/script.h>
10 #include <script/standard.h>
11 #include <sync.h>
12 #include <util.h>
13 #include <utiltime.h>
14 #include <wallet/wallet.h>
15 #include <merkleblock.h>
16 #include <core_io.h>
17 
18 #include <wallet/rpcwallet.h>
19 
20 #include <stdint.h>
21 
22 #include <boost/algorithm/string.hpp>
23 #include <boost/date_time/posix_time/posix_time.hpp>
24 
25 #include <univalue.h>
26 
27 
28 int64_t static DecodeDumpTime(const std::string &str) {
29  static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
30  static const std::locale loc(std::locale::classic(),
31  new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
32  std::istringstream iss(str);
33  iss.imbue(loc);
34  boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
35  iss >> ptime;
36  if (ptime.is_not_a_date_time())
37  return 0;
38  return (ptime - epoch).total_seconds();
39 }
40 
41 std::string static EncodeDumpString(const std::string &str) {
42  std::stringstream ret;
43  for (const unsigned char c : str) {
44  if (c <= 32 || c >= 128 || c == '%') {
45  ret << '%' << HexStr(&c, &c + 1);
46  } else {
47  ret << c;
48  }
49  }
50  return ret.str();
51 }
52 
53 static std::string DecodeDumpString(const std::string &str) {
54  std::stringstream ret;
55  for (unsigned int pos = 0; pos < str.length(); pos++) {
56  unsigned char c = str[pos];
57  if (c == '%' && pos+2 < str.length()) {
58  c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
59  ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
60  pos += 2;
61  }
62  ret << c;
63  }
64  return ret.str();
65 }
66 
67 static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
68 {
69  bool fLabelFound = false;
70  CKey key;
71  pwallet->GetKey(keyid, key);
72  for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) {
73  if (pwallet->mapAddressBook.count(dest)) {
74  if (!strAddr.empty()) {
75  strAddr += ",";
76  }
77  strAddr += EncodeDestination(dest);
78  strLabel = EncodeDumpString(pwallet->mapAddressBook[dest].name);
79  fLabelFound = true;
80  }
81  }
82  if (!fLabelFound) {
84  }
85  return fLabelFound;
86 }
87 
88 static const int64_t TIMESTAMP_MIN = 0;
89 
90 static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver, int64_t time_begin = TIMESTAMP_MIN, bool update = true)
91 {
92  int64_t scanned_time = wallet.RescanFromTime(time_begin, reserver, update);
93  if (wallet.IsAbortingRescan()) {
94  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
95  } else if (scanned_time > time_begin) {
96  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan was unable to fully rescan the blockchain. Some transactions may be missing.");
97  }
98 }
99 
101 {
102  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
103  CWallet* const pwallet = wallet.get();
104  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
105  return NullUniValue;
106  }
107 
108  if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
109  throw std::runtime_error(
110  "importprivkey \"privkey\" ( \"label\" ) ( rescan )\n"
111  "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
112  "Hint: use importmulti to import more than one private key.\n"
113  "\nArguments:\n"
114  "1. \"privkey\" (string, required) The private key (see dumpprivkey)\n"
115  "2. \"label\" (string, optional, default=\"\") An optional label\n"
116  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
117  "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
118  "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"
119  "\nExamples:\n"
120  "\nDump a private key\n"
121  + HelpExampleCli("dumpprivkey", "\"myaddress\"") +
122  "\nImport the private key with rescan\n"
123  + HelpExampleCli("importprivkey", "\"mykey\"") +
124  "\nImport using a label and without rescan\n"
125  + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
126  "\nImport using default blank label and without rescan\n"
127  + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") +
128  "\nAs a JSON-RPC call\n"
129  + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
130  );
131 
132 
133  WalletRescanReserver reserver(pwallet);
134  bool fRescan = true;
135  {
136  LOCK2(cs_main, pwallet->cs_wallet);
137 
138  EnsureWalletIsUnlocked(pwallet);
139 
140  std::string strSecret = request.params[0].get_str();
141  std::string strLabel = "";
142  if (!request.params[1].isNull())
143  strLabel = request.params[1].get_str();
144 
145  // Whether to perform rescan after import
146  if (!request.params[2].isNull())
147  fRescan = request.params[2].get_bool();
148 
149  if (fRescan && fPruneMode)
150  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
151 
152  if (fRescan && !reserver.reserve()) {
153  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
154  }
155 
156  CKey key = DecodeSecret(strSecret);
157  if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
158 
159  CPubKey pubkey = key.GetPubKey();
160  assert(key.VerifyPubKey(pubkey));
161  CKeyID vchAddress = pubkey.GetID();
162  {
163  pwallet->MarkDirty();
164  // We don't know which corresponding address will be used; label them all
165  for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
166  pwallet->SetAddressBook(dest, strLabel, "receive");
167  }
168 
169  // Don't throw error in case a key is already there
170  if (pwallet->HaveKey(vchAddress)) {
171  return NullUniValue;
172  }
173 
174  // whenever a key is imported, we need to scan the whole chain
175  pwallet->UpdateTimeFirstKey(1);
176  pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1;
177 
178  if (!pwallet->AddKeyPubKey(key, pubkey)) {
179  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
180  }
181  pwallet->LearnAllRelatedScripts(pubkey);
182  }
183  }
184  if (fRescan) {
185  RescanWallet(*pwallet, reserver);
186  }
187 
188  return NullUniValue;
189 }
190 
192 {
193  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
194  CWallet* const pwallet = wallet.get();
195  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
196  return NullUniValue;
197  }
198 
199  if (request.fHelp || request.params.size() > 0)
200  throw std::runtime_error(
201  "abortrescan\n"
202  "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
203  "\nExamples:\n"
204  "\nImport a private key\n"
205  + HelpExampleCli("importprivkey", "\"mykey\"") +
206  "\nAbort the running wallet rescan\n"
207  + HelpExampleCli("abortrescan", "") +
208  "\nAs a JSON-RPC call\n"
209  + HelpExampleRpc("abortrescan", "")
210  );
211 
212  if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
213  pwallet->AbortRescan();
214  return true;
215 }
216 
217 static void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
218 static void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
219 {
220  if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
221  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
222  }
223 
224  pwallet->MarkDirty();
225 
226  if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, 0 /* nCreateTime */)) {
227  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
228  }
229 
230  if (isRedeemScript) {
231  const CScriptID id(script);
232  if (!pwallet->HaveCScript(id) && !pwallet->AddCScript(script)) {
233  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
234  }
235  ImportAddress(pwallet, id, strLabel);
236  } else {
237  CTxDestination destination;
238  if (ExtractDestination(script, destination)) {
239  pwallet->SetAddressBook(destination, strLabel, "receive");
240  }
241  }
242 }
243 
244 static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
245 {
246  CScript script = GetScriptForDestination(dest);
247  ImportScript(pwallet, script, strLabel, false);
248  // add to address book or update label
249  if (IsValidDestination(dest))
250  pwallet->SetAddressBook(dest, strLabel, "receive");
251 }
252 
254 {
255  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
256  CWallet* const pwallet = wallet.get();
257  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
258  return NullUniValue;
259  }
260 
261  if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
262  throw std::runtime_error(
263  "importaddress \"address\" ( \"label\" rescan p2sh )\n"
264  "\nAdds an address or script (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"
265  "\nArguments:\n"
266  "1. \"address\" (string, required) The BSHA3 address (or hex-encoded script)\n"
267  "2. \"label\" (string, optional, default=\"\") An optional label\n"
268  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
269  "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
270  "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
271  "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"
272  "If you have the full public key, you should call importpubkey instead of this.\n"
273  "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
274  "as change, and not show up in many RPCs.\n"
275  "\nExamples:\n"
276  "\nImport an address with rescan\n"
277  + HelpExampleCli("importaddress", "\"myaddress\"") +
278  "\nImport using a label without rescan\n"
279  + HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") +
280  "\nAs a JSON-RPC call\n"
281  + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
282  );
283 
284 
285  std::string strLabel;
286  if (!request.params[1].isNull())
287  strLabel = request.params[1].get_str();
288 
289  // Whether to perform rescan after import
290  bool fRescan = true;
291  if (!request.params[2].isNull())
292  fRescan = request.params[2].get_bool();
293 
294  if (fRescan && fPruneMode)
295  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
296 
297  WalletRescanReserver reserver(pwallet);
298  if (fRescan && !reserver.reserve()) {
299  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
300  }
301 
302  // Whether to import a p2sh version, too
303  bool fP2SH = false;
304  if (!request.params[3].isNull())
305  fP2SH = request.params[3].get_bool();
306 
307  {
308  LOCK2(cs_main, pwallet->cs_wallet);
309 
310  CTxDestination dest = DecodeDestination(request.params[0].get_str());
311  if (IsValidDestination(dest)) {
312  if (fP2SH) {
313  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
314  }
315  ImportAddress(pwallet, dest, strLabel);
316  } else if (IsHex(request.params[0].get_str())) {
317  std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
318  ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
319  } else {
320  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid BSHA3 address or script");
321  }
322  }
323  if (fRescan)
324  {
325  RescanWallet(*pwallet, reserver);
326  pwallet->ReacceptWalletTransactions();
327  }
328 
329  return NullUniValue;
330 }
331 
333 {
334  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
335  CWallet* const pwallet = wallet.get();
336  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
337  return NullUniValue;
338  }
339 
340  if (request.fHelp || request.params.size() != 2)
341  throw std::runtime_error(
342  "importprunedfunds\n"
343  "\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"
344  "\nArguments:\n"
345  "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n"
346  "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n"
347  );
348 
350  if (!DecodeHexTx(tx, request.params[0].get_str()))
351  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
352  uint256 hashTx = tx.GetHash();
353  CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
354 
355  CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
356  CMerkleBlock merkleBlock;
357  ssMB >> merkleBlock;
358 
359  //Search partial merkle tree in proof for our transaction and index in valid block
360  std::vector<uint256> vMatch;
361  std::vector<unsigned int> vIndex;
362  unsigned int txnIndex = 0;
363  if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
364 
365  LOCK(cs_main);
366  const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
367  if (!pindex || !chainActive.Contains(pindex)) {
368  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
369  }
370 
371  std::vector<uint256>::const_iterator it;
372  if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) {
373  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction given doesn't exist in proof");
374  }
375 
376  txnIndex = vIndex[it - vMatch.begin()];
377  }
378  else {
379  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Something wrong with merkleblock");
380  }
381 
382  wtx.nIndex = txnIndex;
383  wtx.hashBlock = merkleBlock.header.GetHash();
384 
385  LOCK2(cs_main, pwallet->cs_wallet);
386 
387  if (pwallet->IsMine(*wtx.tx)) {
388  pwallet->AddToWallet(wtx, false);
389  return NullUniValue;
390  }
391 
392  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
393 }
394 
396 {
397  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
398  CWallet* const pwallet = wallet.get();
399  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
400  return NullUniValue;
401  }
402 
403  if (request.fHelp || request.params.size() != 1)
404  throw std::runtime_error(
405  "removeprunedfunds \"txid\"\n"
406  "\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"
407  "\nArguments:\n"
408  "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
409  "\nExamples:\n"
410  + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
411  "\nAs a JSON-RPC call\n"
412  + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
413  );
414 
415  LOCK2(cs_main, pwallet->cs_wallet);
416 
417  uint256 hash(ParseHashV(request.params[0], "txid"));
418  std::vector<uint256> vHash;
419  vHash.push_back(hash);
420  std::vector<uint256> vHashOut;
421 
422  if (pwallet->ZapSelectTx(vHash, vHashOut) != DBErrors::LOAD_OK) {
423  throw JSONRPCError(RPC_WALLET_ERROR, "Could not properly delete the transaction.");
424  }
425 
426  if(vHashOut.empty()) {
427  throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction does not exist in wallet.");
428  }
429 
430  return NullUniValue;
431 }
432 
434 {
435  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
436  CWallet* const pwallet = wallet.get();
437  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
438  return NullUniValue;
439  }
440 
441  if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
442  throw std::runtime_error(
443  "importpubkey \"pubkey\" ( \"label\" rescan )\n"
444  "\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"
445  "\nArguments:\n"
446  "1. \"pubkey\" (string, required) The hex-encoded public key\n"
447  "2. \"label\" (string, optional, default=\"\") An optional label\n"
448  "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
449  "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
450  "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"
451  "\nExamples:\n"
452  "\nImport a public key with rescan\n"
453  + HelpExampleCli("importpubkey", "\"mypubkey\"") +
454  "\nImport using a label without rescan\n"
455  + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
456  "\nAs a JSON-RPC call\n"
457  + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
458  );
459 
460 
461  std::string strLabel;
462  if (!request.params[1].isNull())
463  strLabel = request.params[1].get_str();
464 
465  // Whether to perform rescan after import
466  bool fRescan = true;
467  if (!request.params[2].isNull())
468  fRescan = request.params[2].get_bool();
469 
470  if (fRescan && fPruneMode)
471  throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
472 
473  WalletRescanReserver reserver(pwallet);
474  if (fRescan && !reserver.reserve()) {
475  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
476  }
477 
478  if (!IsHex(request.params[0].get_str()))
479  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
480  std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
481  CPubKey pubKey(data.begin(), data.end());
482  if (!pubKey.IsFullyValid())
483  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
484 
485  {
486  LOCK2(cs_main, pwallet->cs_wallet);
487 
488  for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
489  ImportAddress(pwallet, dest, strLabel);
490  }
491  ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
492  pwallet->LearnAllRelatedScripts(pubKey);
493  }
494  if (fRescan)
495  {
496  RescanWallet(*pwallet, reserver);
497  pwallet->ReacceptWalletTransactions();
498  }
499 
500  return NullUniValue;
501 }
502 
503 
505 {
506  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
507  CWallet* const pwallet = wallet.get();
508  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
509  return NullUniValue;
510  }
511 
512  if (request.fHelp || request.params.size() != 1)
513  throw std::runtime_error(
514  "importwallet \"filename\"\n"
515  "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
516  "\nArguments:\n"
517  "1. \"filename\" (string, required) The wallet file\n"
518  "\nExamples:\n"
519  "\nDump the wallet\n"
520  + HelpExampleCli("dumpwallet", "\"test\"") +
521  "\nImport the wallet\n"
522  + HelpExampleCli("importwallet", "\"test\"") +
523  "\nImport using the json rpc call\n"
524  + HelpExampleRpc("importwallet", "\"test\"")
525  );
526 
527  if (fPruneMode)
528  throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
529 
530  WalletRescanReserver reserver(pwallet);
531  if (!reserver.reserve()) {
532  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
533  }
534 
535  int64_t nTimeBegin = 0;
536  bool fGood = true;
537  {
538  LOCK2(cs_main, pwallet->cs_wallet);
539 
540  EnsureWalletIsUnlocked(pwallet);
541 
542  fsbridge::ifstream file;
543  file.open(request.params[0].get_str(), std::ios::in | std::ios::ate);
544  if (!file.is_open()) {
545  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
546  }
547  nTimeBegin = chainActive.Tip()->GetBlockTime();
548 
549  int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
550  file.seekg(0, file.beg);
551 
552  // Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
553  // we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
554  uiInterface.ShowProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
555  while (file.good()) {
556  uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
557  std::string line;
558  std::getline(file, line);
559  if (line.empty() || line[0] == '#')
560  continue;
561 
562  std::vector<std::string> vstr;
563  boost::split(vstr, line, boost::is_any_of(" "));
564  if (vstr.size() < 2)
565  continue;
566  CKey key = DecodeSecret(vstr[0]);
567  if (key.IsValid()) {
568  CPubKey pubkey = key.GetPubKey();
569  assert(key.VerifyPubKey(pubkey));
570  CKeyID keyid = pubkey.GetID();
571  if (pwallet->HaveKey(keyid)) {
572  pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
573  continue;
574  }
575  int64_t nTime = DecodeDumpTime(vstr[1]);
576  std::string strLabel;
577  bool fLabel = true;
578  for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
579  if (vstr[nStr].front() == '#')
580  break;
581  if (vstr[nStr] == "change=1")
582  fLabel = false;
583  if (vstr[nStr] == "reserve=1")
584  fLabel = false;
585  if (vstr[nStr].substr(0,6) == "label=") {
586  strLabel = DecodeDumpString(vstr[nStr].substr(6));
587  fLabel = true;
588  }
589  }
590  pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid));
591  if (!pwallet->AddKeyPubKey(key, pubkey)) {
592  fGood = false;
593  continue;
594  }
595  pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
596  if (fLabel)
597  pwallet->SetAddressBook(keyid, strLabel, "receive");
598  nTimeBegin = std::min(nTimeBegin, nTime);
599  } else if(IsHex(vstr[0])) {
600  std::vector<unsigned char> vData(ParseHex(vstr[0]));
601  CScript script = CScript(vData.begin(), vData.end());
602  CScriptID id(script);
603  if (pwallet->HaveCScript(id)) {
604  pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
605  continue;
606  }
607  if(!pwallet->AddCScript(script)) {
608  pwallet->WalletLogPrintf("Error importing script %s\n", vstr[0]);
609  fGood = false;
610  continue;
611  }
612  int64_t birth_time = DecodeDumpTime(vstr[1]);
613  if (birth_time > 0) {
614  pwallet->m_script_metadata[id].nCreateTime = birth_time;
615  nTimeBegin = std::min(nTimeBegin, birth_time);
616  }
617  }
618  }
619  file.close();
620  uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
621  pwallet->UpdateTimeFirstKey(nTimeBegin);
622  }
623  uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
624  RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */);
625  pwallet->MarkDirty();
626 
627  if (!fGood)
628  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys/scripts to wallet");
629 
630  return NullUniValue;
631 }
632 
634 {
635  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
636  CWallet* const pwallet = wallet.get();
637  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
638  return NullUniValue;
639  }
640 
641  if (request.fHelp || request.params.size() != 1)
642  throw std::runtime_error(
643  "dumpprivkey \"address\"\n"
644  "\nReveals the private key corresponding to 'address'.\n"
645  "Then the importprivkey can be used with this output\n"
646  "\nArguments:\n"
647  "1. \"address\" (string, required) The bitcoin address for the private key\n"
648  "\nResult:\n"
649  "\"key\" (string) The private key\n"
650  "\nExamples:\n"
651  + HelpExampleCli("dumpprivkey", "\"myaddress\"")
652  + HelpExampleCli("importprivkey", "\"mykey\"")
653  + HelpExampleRpc("dumpprivkey", "\"myaddress\"")
654  );
655 
656  LOCK2(cs_main, pwallet->cs_wallet);
657 
658  EnsureWalletIsUnlocked(pwallet);
659 
660  std::string strAddress = request.params[0].get_str();
661  CTxDestination dest = DecodeDestination(strAddress);
662  if (!IsValidDestination(dest)) {
663  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid BSHA3 address");
664  }
665  auto keyid = GetKeyForDestination(*pwallet, dest);
666  if (keyid.IsNull()) {
667  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
668  }
669  CKey vchSecret;
670  if (!pwallet->GetKey(keyid, vchSecret)) {
671  throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
672  }
673  return EncodeSecret(vchSecret);
674 }
675 
676 
678 {
679  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
680  CWallet* const pwallet = wallet.get();
681  if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
682  return NullUniValue;
683  }
684 
685  if (request.fHelp || request.params.size() != 1)
686  throw std::runtime_error(
687  "dumpwallet \"filename\"\n"
688  "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
689  "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n"
690  "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"
691  "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n"
692  "\nArguments:\n"
693  "1. \"filename\" (string, required) The filename with path (either absolute or relative to bsha3d)\n"
694  "\nResult:\n"
695  "{ (json object)\n"
696  " \"filename\" : { (string) The filename with full absolute path\n"
697  "}\n"
698  "\nExamples:\n"
699  + HelpExampleCli("dumpwallet", "\"test\"")
700  + HelpExampleRpc("dumpwallet", "\"test\"")
701  );
702 
703  LOCK2(cs_main, pwallet->cs_wallet);
704 
705  EnsureWalletIsUnlocked(pwallet);
706 
707  fs::path filepath = request.params[0].get_str();
708  filepath = fs::absolute(filepath);
709 
710  /* Prevent arbitrary files from being overwritten. There have been reports
711  * that users have overwritten wallet files this way:
712  * https://github.com/bitcoin/bitcoin/issues/9934
713  * It may also avoid other security issues.
714  */
715  if (fs::exists(filepath)) {
716  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");
717  }
718 
719  fsbridge::ofstream file;
720  file.open(filepath);
721  if (!file.is_open())
722  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
723 
724  std::map<CTxDestination, int64_t> mapKeyBirth;
725  const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys();
726  pwallet->GetKeyBirthTimes(mapKeyBirth);
727 
728  std::set<CScriptID> scripts = pwallet->GetCScripts();
729  // TODO: include scripts in GetKeyBirthTimes() output instead of separate
730 
731  // sort time/key pairs
732  std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
733  for (const auto& entry : mapKeyBirth) {
734  if (const CKeyID* keyID = boost::get<CKeyID>(&entry.first)) { // set and test
735  vKeyBirth.push_back(std::make_pair(entry.second, *keyID));
736  }
737  }
738  mapKeyBirth.clear();
739  std::sort(vKeyBirth.begin(), vKeyBirth.end());
740 
741  // produce output
742  file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
743  file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
744  file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
745  file << strprintf("# mined on %s\n", FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()));
746  file << "\n";
747 
748  // add the base58check encoded extended master if the wallet uses HD
749  CKeyID seed_id = pwallet->GetHDChain().seed_id;
750  if (!seed_id.IsNull())
751  {
752  CKey seed;
753  if (pwallet->GetKey(seed_id, seed)) {
754  CExtKey masterKey;
755  masterKey.SetSeed(seed.begin(), seed.size());
756 
757  file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n";
758  }
759  }
760  for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
761  const CKeyID &keyid = it->second;
762  std::string strTime = FormatISO8601DateTime(it->first);
763  std::string strAddr;
764  std::string strLabel;
765  CKey key;
766  if (pwallet->GetKey(keyid, key)) {
767  file << strprintf("%s %s ", EncodeSecret(key), strTime);
768  if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
769  file << strprintf("label=%s", strLabel);
770  } else if (keyid == seed_id) {
771  file << "hdseed=1";
772  } else if (mapKeyPool.count(keyid)) {
773  file << "reserve=1";
774  } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "s") {
775  file << "inactivehdseed=1";
776  } else {
777  file << "change=1";
778  }
779  file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwallet->mapKeyMetadata[keyid].hdKeypath : ""));
780  }
781  }
782  file << "\n";
783  for (const CScriptID &scriptid : scripts) {
784  CScript script;
785  std::string create_time = "0";
786  std::string address = EncodeDestination(scriptid);
787  // get birth times for scripts with metadata
788  auto it = pwallet->m_script_metadata.find(scriptid);
789  if (it != pwallet->m_script_metadata.end()) {
790  create_time = FormatISO8601DateTime(it->second.nCreateTime);
791  }
792  if(pwallet->GetCScript(scriptid, script)) {
793  file << strprintf("%s %s script=1", HexStr(script.begin(), script.end()), create_time);
794  file << strprintf(" # addr=%s\n", address);
795  }
796  }
797  file << "\n";
798  file << "# End of dump\n";
799  file.close();
800 
801  UniValue reply(UniValue::VOBJ);
802  reply.pushKV("filename", filepath.string());
803 
804  return reply;
805 }
806 
807 
808 static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
809 {
810  try {
811  // First ensure scriptPubKey has either a script or JSON with "address" string
812  const UniValue& scriptPubKey = data["scriptPubKey"];
813  bool isScript = scriptPubKey.getType() == UniValue::VSTR;
814  if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) {
815  throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string");
816  }
817  const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
818 
819  // Optional fields.
820  const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
821  const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : "";
822  const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
823  const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
824  const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
825  const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
826  const std::string& label = data.exists("label") ? data["label"].get_str() : "";
827 
828  // Generate the script and destination for the scriptPubKey provided
829  CScript script;
830  CTxDestination dest;
831 
832  if (!isScript) {
833  dest = DecodeDestination(output);
834  if (!IsValidDestination(dest)) {
835  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
836  }
837  script = GetScriptForDestination(dest);
838  } else {
839  if (!IsHex(output)) {
840  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey");
841  }
842 
843  std::vector<unsigned char> vData(ParseHex(output));
844  script = CScript(vData.begin(), vData.end());
845  if (!ExtractDestination(script, dest) && !internal) {
846  throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
847  }
848  }
849 
850  // Watchonly and private keys
851  if (watchOnly && keys.size()) {
852  throw JSONRPCError(RPC_INVALID_PARAMETER, "Watch-only addresses should not include private keys");
853  }
854 
855  // Internal addresses should not have a label
856  if (internal && data.exists("label")) {
857  throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
858  }
859 
860  // Force users to provide the witness script in its field rather than redeemscript
861  if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) {
862  throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WSH addresses have an empty redeemscript. Please provide the witnessscript instead.");
863  }
864 
865  CScript scriptpubkey_script = script;
866  CTxDestination scriptpubkey_dest = dest;
867  bool allow_p2wpkh = true;
868 
869  // P2SH
870  if (!strRedeemScript.empty() && script.IsPayToScriptHash()) {
871  // Check the redeemScript is valid
872  if (!IsHex(strRedeemScript)) {
873  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script: must be hex string");
874  }
875 
876  // Import redeem script.
877  std::vector<unsigned char> vData(ParseHex(strRedeemScript));
878  CScript redeemScript = CScript(vData.begin(), vData.end());
879  CScriptID redeem_id(redeemScript);
880 
881  // Check that the redeemScript and scriptPubKey match
882  if (GetScriptForDestination(redeem_id) != script) {
883  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The redeemScript does not match the scriptPubKey");
884  }
885 
886  pwallet->MarkDirty();
887 
888  if (!pwallet->AddWatchOnly(redeemScript, timestamp)) {
889  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
890  }
891 
892  if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) {
893  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
894  }
895 
896  // Now set script to the redeemScript so we parse the inner script as P2WSH or P2WPKH below
897  script = redeemScript;
898  ExtractDestination(script, dest);
899  }
900 
901  // (P2SH-)P2WSH
902  if (!witness_script_hex.empty() && script.IsPayToWitnessScriptHash()) {
903  if (!IsHex(witness_script_hex)) {
904  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script: must be hex string");
905  }
906 
907  // Generate the scripts
908  std::vector<unsigned char> witness_script_parsed(ParseHex(witness_script_hex));
909  CScript witness_script = CScript(witness_script_parsed.begin(), witness_script_parsed.end());
910  CScriptID witness_id(witness_script);
911 
912  // Check that the witnessScript and scriptPubKey match
913  if (GetScriptForDestination(WitnessV0ScriptHash(witness_script)) != script) {
914  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The witnessScript does not match the scriptPubKey or redeemScript");
915  }
916 
917  // Add the witness script as watch only only if it is not for P2SH-P2WSH
918  if (!scriptpubkey_script.IsPayToScriptHash() && !pwallet->AddWatchOnly(witness_script, timestamp)) {
919  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
920  }
921 
922  if (!pwallet->HaveCScript(witness_id) && !pwallet->AddCScript(witness_script)) {
923  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2wsh witnessScript to wallet");
924  }
925 
926  // Now set script to the witnessScript so we parse the inner script as P2PK or P2PKH below
927  script = witness_script;
928  ExtractDestination(script, dest);
929  allow_p2wpkh = false; // P2WPKH cannot be embedded in P2WSH
930  }
931 
932  // (P2SH-)P2PK/P2PKH/P2WPKH
933  if (dest.type() == typeid(CKeyID) || dest.type() == typeid(WitnessV0KeyHash)) {
934  if (!allow_p2wpkh && dest.type() == typeid(WitnessV0KeyHash)) {
935  throw JSONRPCError(RPC_INVALID_PARAMETER, "P2WPKH cannot be embedded in P2WSH");
936  }
937  if (keys.size() > 1 || pubKeys.size() > 1) {
938  throw JSONRPCError(RPC_INVALID_PARAMETER, "More than one key given for one single-key address");
939  }
940  CPubKey pubkey;
941  if (keys.size()) {
942  pubkey = DecodeSecret(keys[0].get_str()).GetPubKey();
943  }
944  if (pubKeys.size()) {
945  const std::string& strPubKey = pubKeys[0].get_str();
946  if (!IsHex(strPubKey)) {
947  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
948  }
949  std::vector<unsigned char> vData(ParseHex(pubKeys[0].get_str()));
950  CPubKey pubkey_temp(vData.begin(), vData.end());
951  if (pubkey.size() && pubkey_temp != pubkey) {
952  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key does not match public key for address");
953  }
954  pubkey = pubkey_temp;
955  }
956  if (pubkey.size() > 0) {
957  if (!pubkey.IsFullyValid()) {
958  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
959  }
960 
961  // Check the key corresponds to the destination given
962  std::vector<CTxDestination> destinations = GetAllDestinationsForKey(pubkey);
963  if (std::find(destinations.begin(), destinations.end(), dest) == destinations.end()) {
964  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Key does not match address destination");
965  }
966 
967  // This is necessary to force the wallet to import the pubKey
968  CScript scriptRawPubKey = GetScriptForRawPubKey(pubkey);
969 
970  if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
971  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
972  }
973 
974  pwallet->MarkDirty();
975 
976  if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
977  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
978  }
979  }
980  }
981 
982  // Import the address
983  if (::IsMine(*pwallet, scriptpubkey_script) == ISMINE_SPENDABLE) {
984  throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
985  }
986 
987  pwallet->MarkDirty();
988 
989  if (!pwallet->AddWatchOnly(scriptpubkey_script, timestamp)) {
990  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
991  }
992 
993  if (!watchOnly && !pwallet->HaveCScript(CScriptID(scriptpubkey_script)) && !pwallet->AddCScript(scriptpubkey_script)) {
994  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding scriptPubKey script to wallet");
995  }
996 
997  // add to address book or update label
998  if (IsValidDestination(scriptpubkey_dest)) {
999  pwallet->SetAddressBook(scriptpubkey_dest, label, "receive");
1000  }
1001 
1002  // Import private keys.
1003  for (size_t i = 0; i < keys.size(); i++) {
1004  const std::string& strPrivkey = keys[i].get_str();
1005 
1006  // Checks.
1007  CKey key = DecodeSecret(strPrivkey);
1008 
1009  if (!key.IsValid()) {
1010  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1011  }
1012 
1013  CPubKey pubKey = key.GetPubKey();
1014  assert(key.VerifyPubKey(pubKey));
1015 
1016  CKeyID vchAddress = pubKey.GetID();
1017  pwallet->MarkDirty();
1018 
1019  if (pwallet->HaveKey(vchAddress)) {
1020  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
1021  }
1022 
1023  pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
1024 
1025  if (!pwallet->AddKeyPubKey(key, pubKey)) {
1026  throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
1027  }
1028 
1029  pwallet->UpdateTimeFirstKey(timestamp);
1030  }
1031 
1032  UniValue result = UniValue(UniValue::VOBJ);
1033  result.pushKV("success", UniValue(true));
1034  return result;
1035  } catch (const UniValue& e) {
1036  UniValue result = UniValue(UniValue::VOBJ);
1037  result.pushKV("success", UniValue(false));
1038  result.pushKV("error", e);
1039  return result;
1040  } catch (...) {
1041  UniValue result = UniValue(UniValue::VOBJ);
1042  result.pushKV("success", UniValue(false));
1043  result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields"));
1044  return result;
1045  }
1046 }
1047 
1048 static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
1049 {
1050  if (data.exists("timestamp")) {
1051  const UniValue& timestamp = data["timestamp"];
1052  if (timestamp.isNum()) {
1053  return timestamp.get_int64();
1054  } else if (timestamp.isStr() && timestamp.get_str() == "now") {
1055  return now;
1056  }
1057  throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected number or \"now\" timestamp value for key. got type %s", uvTypeName(timestamp.type())));
1058  }
1059  throw JSONRPCError(RPC_TYPE_ERROR, "Missing required timestamp field for key");
1060 }
1061 
1063 {
1064  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest);
1065  CWallet* const pwallet = wallet.get();
1066  if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
1067  return NullUniValue;
1068  }
1069 
1070  // clang-format off
1071  if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
1072  throw std::runtime_error(
1073  "importmulti \"requests\" ( \"options\" )\n\n"
1074  "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"
1075  "Arguments:\n"
1076  "1. requests (array, required) Data to be imported\n"
1077  " [ (array of json objects)\n"
1078  " {\n"
1079  " \"scriptPubKey\": \"<script>\" | { \"address\":\"<address>\" }, (string / json, required) Type of scriptPubKey (string for script, json for address)\n"
1080  " \"timestamp\": timestamp | \"now\" , (integer / string, required) Creation time of the key in seconds since epoch (Jan 1 1970 GMT),\n"
1081  " or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
1082  " key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
1083  " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
1084  " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
1085  " creation time of all keys being imported by the importmulti call will be scanned.\n"
1086  " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey\n"
1087  " \"witnessscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey\n"
1088  " \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n"
1089  " \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n"
1090  " \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n"
1091  " \"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"
1092  " \"label\": <label> , (string, optional, default: '') Label to assign to the address, only allowed with internal=false\n"
1093  " }\n"
1094  " ,...\n"
1095  " ]\n"
1096  "2. options (json, optional)\n"
1097  " {\n"
1098  " \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n"
1099  " }\n"
1100  "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
1101  "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n"
1102  "\nExamples:\n" +
1103  HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
1104  "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1105  HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") +
1106 
1107  "\nResponse is an array with the same size as the input that has the execution result :\n"
1108  " [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
1109 
1110  // clang-format on
1111 
1112  RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
1113 
1114  const UniValue& requests = mainRequest.params[0];
1115 
1116  //Default options
1117  bool fRescan = true;
1118 
1119  if (!mainRequest.params[1].isNull()) {
1120  const UniValue& options = mainRequest.params[1];
1121 
1122  if (options.exists("rescan")) {
1123  fRescan = options["rescan"].get_bool();
1124  }
1125  }
1126 
1127  WalletRescanReserver reserver(pwallet);
1128  if (fRescan && !reserver.reserve()) {
1129  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
1130  }
1131 
1132  int64_t now = 0;
1133  bool fRunScan = false;
1134  int64_t nLowestTimestamp = 0;
1135  UniValue response(UniValue::VARR);
1136  {
1137  LOCK2(cs_main, pwallet->cs_wallet);
1138  EnsureWalletIsUnlocked(pwallet);
1139 
1140  // Verify all timestamps are present before importing any keys.
1141  now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
1142  for (const UniValue& data : requests.getValues()) {
1143  GetImportTimestamp(data, now);
1144  }
1145 
1146  const int64_t minimumTimestamp = 1;
1147 
1148  if (fRescan && chainActive.Tip()) {
1149  nLowestTimestamp = chainActive.Tip()->GetBlockTime();
1150  } else {
1151  fRescan = false;
1152  }
1153 
1154  for (const UniValue& data : requests.getValues()) {
1155  const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
1156  const UniValue result = ProcessImport(pwallet, data, timestamp);
1157  response.push_back(result);
1158 
1159  if (!fRescan) {
1160  continue;
1161  }
1162 
1163  // If at least one request was successful then allow rescan.
1164  if (result["success"].get_bool()) {
1165  fRunScan = true;
1166  }
1167 
1168  // Get the lowest timestamp.
1169  if (timestamp < nLowestTimestamp) {
1170  nLowestTimestamp = timestamp;
1171  }
1172  }
1173  }
1174  if (fRescan && fRunScan && requests.size()) {
1175  int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
1176  pwallet->ReacceptWalletTransactions();
1177 
1178  if (pwallet->IsAbortingRescan()) {
1179  throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
1180  }
1181  if (scannedTime > nLowestTimestamp) {
1182  std::vector<UniValue> results = response.getValues();
1183  response.clear();
1184  response.setArray();
1185  size_t i = 0;
1186  for (const UniValue& request : requests.getValues()) {
1187  // If key creation date is within the successfully scanned
1188  // range, or if the import result already has an error set, let
1189  // the result stand unmodified. Otherwise replace the result
1190  // with an error message.
1191  if (scannedTime <= GetImportTimestamp(request, now) || results.at(i).exists("error")) {
1192  response.push_back(results.at(i));
1193  } else {
1194  UniValue result = UniValue(UniValue::VOBJ);
1195  result.pushKV("success", UniValue(false));
1196  result.pushKV(
1197  "error",
1198  JSONRPCError(
1200  strprintf("Rescan failed for key with creation timestamp %d. There was an error reading a "
1201  "block from time %d, which is after or within %d seconds of key creation, and "
1202  "could contain transactions pertaining to the key. As a result, transactions "
1203  "and coins using this key may not appear in the wallet. This error could be "
1204  "caused by pruning or data corruption (see bsha3d log for details) and could "
1205  "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1206  "and -rescan options).",
1207  GetImportTimestamp(request, now), scannedTime - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW)));
1208  response.push_back(std::move(result));
1209  }
1210  ++i;
1211  }
1212  }
1213  }
1214 
1215  return response;
1216 }
UniValue abortrescan(const JSONRPCRequest &request)
Definition: rpcdump.cpp:191
bool fPruneMode
True if we&#39;re running in -prune mode.
Definition: validation.cpp:228
const std::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:155
bool HaveKey(const CKeyID &address) const override
Check whether a key corresponding to a given address is present in the store.
Definition: crypter.cpp:252
int64_t GetBlockTime() const
Definition: chain.h:297
bool get_bool() const
void GetKeyBirthTimes(std::map< CTxDestination, int64_t > &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3644
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
Definition: wallet.h:961
UniValue dumpprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:633
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:763
#define strprintf
Definition: tinyformat.h:1066
bool IsPayToScriptHash() const
Definition: script.cpp:197
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:227
UniValue importmulti(const JSONRPCRequest &mainRequest)
Definition: rpcdump.cpp:1062
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:179
int nIndex
Definition: wallet.h:226
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
Definition: rpcwallet.cpp:73
bool HaveCScript(const CScriptID &hash) const override
Definition: keystore.cpp:96
UniValue ret(UniValue::VARR)
Definition: rpcwallet.cpp:1140
std::set< CScriptID > GetCScripts() const override
Definition: keystore.cpp:102
Definition: key.h:141
void ReacceptWalletTransactions()
Definition: wallet.cpp:1710
bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
Definition: keystore.cpp:112
int Height() const
Return the maximal height in the chain.
Definition: chain.h:476
uint256 hashBlock
Definition: wallet.h:219
fs::ifstream ifstream
Definition: fs.h:90
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:324
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:296
UniValue dumpwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:677
CKeyID GetKeyForDestination(const CKeyStore &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
Definition: keystore.cpp:177
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:516
bool isStr() const
Definition: univalue.h:82
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:221
int64_t get_int64() const
fs::ofstream ofstream
Definition: fs.h:91
const unsigned char * begin() const
Definition: key.h:89
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:155
bool IsNull() const
Definition: uint256.h:32
Invalid, missing or duplicate parameter.
Definition: protocol.h:52
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: server.cpp:117
std::vector< CTxDestination > GetAllDestinationsForKey(const CPubKey &key)
Get all destinations (potentially) supported by the wallet for the given key.
Definition: outputtype.cpp:64
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3036
uint256 GetBlockHash() const
Definition: chain.h:292
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3092
iterator end()
Definition: prevector.h:303
void MarkDirty()
Definition: wallet.cpp:805
#define LOCK2(cs1, cs2)
Definition: sync.h:182
const char * uvTypeName(UniValue::VType t)
Definition: univalue.cpp:219
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
Definition: merkleblock.h:133
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
CCriticalSection cs_main
Definition: validation.cpp:216
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid()) ...
Definition: pubkey.cpp:206
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:1136
CTransactionRef tx
Definition: wallet.h:218
UniValue params
Definition: server.h:44
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Update wallet first key creation time.
Definition: wallet.cpp:343
boost::variant< CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:123
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
Definition: wallet.cpp:355
OutputType m_default_address_type
Definition: wallet.h:931
#define LOCK(cs)
Definition: sync.h:181
bool exists(const std::string &key) const
Definition: univalue.h:76
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:463
UniValue removeprunedfunds(const JSONRPCRequest &request)
Definition: rpcdump.cpp:395
An encapsulated public key.
Definition: pubkey.h:30
bool IsHex(const std::string &str)
Unexpected type was passed as parameter.
Definition: protocol.h:49
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Adds a key to the store, and saves it to disk.
Definition: wallet.cpp:296
General application defined errors.
Definition: protocol.h:48
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool GetKey(const CKeyID &address, CKey &keyOut) const override
Definition: crypter.cpp:261
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: server.cpp:51
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:88
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:109
std::string ToString() const
Definition: uint256.cpp:62
Invalid address or key.
Definition: protocol.h:50
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:288
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: server.cpp:511
CCriticalSection cs_wallet
Definition: wallet.h:709
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: rpcwallet.cpp:53
bool isNull() const
Definition: univalue.h:78
void SetSeed(const unsigned char *seed, unsigned int nSeedLen)
Definition: key.cpp:296
bool AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose=true)
Definition: wallet.cpp:843
int64_t GetMedianTimePast() const
Definition: chain.h:309
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1176
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:295
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string strName)
Definition: server.cpp:130
bool AddWatchOnly(const CScript &dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Private version of AddWatchOnly method which does not accept a timestamp, and which will reset the wa...
Definition: wallet.cpp:377
bool fHelp
Definition: server.h:45
256-bit opaque blob.
Definition: uint256.h:122
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:214
enum VType type() const
Definition: univalue.h:178
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
bool setArray()
Definition: univalue.cpp:94
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:60
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
Definition: utiltime.cpp:79
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:384
UniValue importpubkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:433
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey)
Definition: ismine.cpp:175
A reference to a CKey: the Hash360 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:445
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
Definition: core_read.cpp:113
bool IsScanning()
Definition: wallet.h:810
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:599
const UniValue NullUniValue
Definition: univalue.cpp:13
UniValue importprivkey(const JSONRPCRequest &request)
Definition: rpcdump.cpp:100
void AbortRescan()
Definition: wallet.h:808
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
Definition: outputtype.cpp:45
iterator begin()
Definition: prevector.h:301
UniValue importwallet(const JSONRPCRequest &request)
Definition: rpcdump.cpp:504
A reference to a CScript: the Hash360 of its serialization (see script.h)
Definition: standard.h:22
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:209
UniValue importaddress(const JSONRPCRequest &request)
Definition: rpcdump.cpp:253
A mutable version of CTransaction.
Definition: transaction.h:360
Wallet errors.
Definition: protocol.h:76
bool IsAbortingRescan()
Definition: wallet.h:809
const std::string GetDisplayName() const
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
Definition: wallet.h:1129
UniValue JSONRPCError(int code, const std::string &message)
Definition: protocol.cpp:51
void clear()
Definition: univalue.cpp:15
size_t size() const
Definition: univalue.h:69
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:20
An encapsulated private key.
Definition: key.h:27
bool HaveWatchOnly(const CScript &dest) const override
Definition: keystore.cpp:165
CClientUIInterface uiInterface
void LearnAllRelatedScripts(const CPubKey &key)
Same as LearnRelatedScripts, but when the OutputType is not known (and could be anything).
Definition: wallet.cpp:4285
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:133
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
Definition: wallet.cpp:1592
isminetype IsMine(const CTxIn &txin) const
Definition: wallet.cpp:1218
CChain & chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:219
const CHDChain & GetHDChain() const
Definition: wallet.h:1079
CKeyID seed_id
seed hash360
Definition: walletdb.h:63
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:149
const std::string CLIENT_BUILD
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:198
UniValue importprunedfunds(const JSONRPCRequest &request)
Definition: rpcdump.cpp:332
std::string _(const char *psz)
Translation function.
Definition: util.h:50
Error parsing or validating structure in raw format.
Definition: protocol.h:54
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:206
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
void EnsureWalletIsUnlocked(CWallet *const pwallet)
Definition: rpcwallet.cpp:85
std::vector< unsigned char > ParseHex(const char *psz)
CBlockIndex * LookupBlockIndex(const uint256 &hash)
Definition: validation.h:431