29 #include <boost/algorithm/string.hpp>
42 std::stringstream ret;
43 for (
const uint8_t c : str) {
44 if (c <= 32 || c >= 128 || c ==
'%') {
45 ret << '%' << HexStr(Span<const uint8_t>(&c, 1));
54 std::stringstream ret;
55 for (
unsigned int pos = 0; pos < str.length(); 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));
70 std::string &strAddr, std::string &strLabel)
72 bool fLabelFound =
false;
74 spk_man->GetKey(keyid, key);
76 const auto *address_book_entry = pwallet->FindAddressBookEntry(dest);
77 if (address_book_entry) {
78 if (!strAddr.empty()) {
89 pwallet->m_default_address_type),
100 int64_t scanned_time =
wallet.RescanFromTime(time_begin, reserver, update);
101 if (
wallet.IsAbortingRescan()) {
103 }
else if (scanned_time > time_begin) {
105 "Rescan was unable to fully rescan the blockchain. "
106 "Some transactions may be missing.");
113 "Adds a private key (as returned by dumpprivkey) to your wallet. "
114 "Requires a new wallet backup.\n"
115 "Hint: use importmulti to import more than one private key.\n"
116 "\nNote: This call can take minutes to complete if rescan is true, "
117 "during that time, other rpc calls\n"
118 "may report that the imported key exists but related transactions are "
119 "still missing, leading to temporarily incorrect/bogus balances and "
120 "unspent outputs until rescan completes.\n"
121 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
124 "The private key (see dumpprivkey)"},
126 "current label if address exists, otherwise \"\"",
127 "An optional label"},
129 "Rescan the wallet for transactions"},
133 "\nDump a private key\n" +
135 "\nImport the private key with rescan\n" +
137 "\nImport using a label and without rescan\n" +
139 "\nImport using default blank label and without rescan\n" +
141 "\nAs a JSON-RPC call\n" +
142 HelpExampleRpc(
"importprivkey",
"\"mykey\", \"testing\", false")},
145 std::shared_ptr<CWallet>
const wallet =
155 "Cannot import private keys to a wallet with "
156 "private keys disabled");
168 std::string strSecret = request.params[0].get_str();
169 std::string strLabel =
"";
170 if (!request.params[1].isNull()) {
171 strLabel = request.params[1].get_str();
175 if (!request.params[2].isNull()) {
176 fRescan = request.params[2].get_bool();
185 "Rescan is disabled when blocks are pruned");
188 if (fRescan && !reserver.
reserve()) {
191 "Wallet is currently rescanning. Abort existing "
198 "Invalid private key encoding");
211 if (!request.params[1].isNull() ||
220 "Error adding key to wallet");
236 "Stops current wallet rescan triggered by an RPC call, e.g. by an "
237 "importprivkey call.\n"
238 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
241 "Whether the abort was successful"},
244 "\nAbort the running wallet rescan\n" +
246 "\nAs a JSON-RPC call\n" +
250 std::shared_ptr<CWallet>
const wallet =
269 "Adds an address or script (in hex) that can be watched as if it "
270 "were in your wallet but cannot be used to spend. Requires a new "
272 "\nNote: This call can take minutes to complete if rescan is true, "
273 "during that time, other rpc calls\n"
274 "may report that the imported address exists but related transactions "
275 "are still missing, leading to temporarily incorrect/bogus balances "
276 "and unspent outputs until rescan completes.\n"
277 "If you have the full public key, you should call importpubkey instead "
279 "Hint: use importmulti to import more than one address.\n"
280 "\nNote: If you import a non-standard raw script in hex form, outputs "
281 "sending to it will be treated\n"
282 "as change, and not show up in many RPCs.\n"
283 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
286 "The Bitcoin address (or hex-encoded script)"},
288 "An optional label"},
290 "Rescan the wallet for transactions"},
292 "Add the P2SH version of the script as well"},
296 "\nImport an address with rescan\n" +
298 "\nImport using a label without rescan\n" +
299 HelpExampleCli(
"importaddress",
"\"myaddress\" \"testing\" false") +
300 "\nAs a JSON-RPC call\n" +
302 "\"myaddress\", \"testing\", false")},
305 std::shared_ptr<CWallet>
const wallet =
314 std::string strLabel;
315 if (!request.params[1].isNull()) {
316 strLabel = request.params[1].get_str();
321 if (!request.params[2].isNull()) {
322 fRescan = request.params[2].get_bool();
330 "Rescan is disabled when blocks are pruned");
334 if (fRescan && !reserver.
reserve()) {
336 "Wallet is currently rescanning. Abort "
337 "existing rescan or wait.");
342 if (!request.params[3].isNull()) {
343 fP2SH = request.params[3].get_bool();
350 request.params[0].get_str(),
wallet->GetChainParams());
355 "Cannot use the p2sh flag with an address - "
356 "use a script instead");
365 }
else if (
IsHex(request.params[0].get_str())) {
366 std::vector<uint8_t> data(
367 ParseHex(request.params[0].get_str()));
368 CScript redeem_script(data.begin(), data.end());
370 std::set<CScript> scripts = {redeem_script};
379 strLabel, scripts,
false ,
383 "Invalid Bitcoin address or script");
402 "Imports funds without rescan. Corresponding address or script must "
403 "previously be included in wallet. Aimed towards pruned wallets. The "
404 "end-user is responsible to import additional transactions that "
405 "subsequently spend the imported outputs or rescan after the point in "
406 "the blockchain the transaction is included.\n",
409 "A raw transaction in hex funding an already-existing address in "
412 "The hex output from gettxoutproof that contains the transaction"},
418 std::shared_ptr<CWallet>
const wallet =
426 if (!
DecodeHexTx(tx, request.params[0].get_str())) {
439 std::vector<uint256> vMatch;
440 std::vector<size_t> vIndex;
444 "Something wrong with merkleblock");
453 "Block not found in chain");
456 std::vector<uint256>::const_iterator it;
457 if ((it = std::find(vMatch.begin(), vMatch.end(), txid)) ==
460 "Transaction given doesn't exist in proof");
463 size_t txnIndex = vIndex[it - vMatch.begin()];
466 CWalletTx::Status::CONFIRMED, height,
470 if (pwallet->
IsMine(*tx_ref)) {
477 "No addresses in wallet correspond to included transaction");
485 "Deletes the specified transaction from the wallet. Meant for use "
486 "with pruned wallets and as a companion to importprunedfunds. This "
487 "will affect wallet balances.\n",
490 "The hex-encoded id of the transaction you are deleting"},
494 "\"a8d0c0184dde994a09ec054286f1ce581bebf4644"
495 "6a512166eae7628734ea0a5\"") +
496 "\nAs a JSON-RPC call\n" +
498 "\"a8d0c0184dde994a09ec054286f1ce581bebf4644"
499 "6a512166eae7628734ea0a5\"")},
502 std::shared_ptr<CWallet>
const wallet =
512 std::vector<TxId> txIds;
513 txIds.push_back(txid);
514 std::vector<TxId> txIdsOut;
519 "Could not properly delete the transaction.");
522 if (txIdsOut.empty()) {
524 "Transaction does not exist in wallet.");
535 "Adds a public key (in hex) that can be watched as if it were in "
536 "your wallet but cannot be used to spend. Requires a new wallet "
538 "Hint: use importmulti to import more than one public key.\n"
539 "\nNote: This call can take minutes to complete if rescan is true, "
540 "during that time, other rpc calls\n"
541 "may report that the imported pubkey exists but related transactions "
542 "are still missing, leading to temporarily incorrect/bogus balances "
543 "and unspent outputs until rescan completes.\n"
544 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
547 "The hex-encoded public key"},
549 "An optional label"},
551 "Rescan the wallet for transactions"},
555 "\nImport a public key with rescan\n" +
557 "\nImport using a label without rescan\n" +
558 HelpExampleCli(
"importpubkey",
"\"mypubkey\" \"testing\" false") +
559 "\nAs a JSON-RPC call\n" +
560 HelpExampleRpc(
"importpubkey",
"\"mypubkey\", \"testing\", false")},
563 std::shared_ptr<CWallet>
const wallet =
572 std::string strLabel;
573 if (!request.params[1].isNull()) {
574 strLabel = request.params[1].get_str();
579 if (!request.params[2].isNull()) {
580 fRescan = request.params[2].get_bool();
588 "Rescan is disabled when blocks are pruned");
592 if (fRescan && !reserver.
reserve()) {
594 "Wallet is currently rescanning. Abort "
595 "existing rescan or wait.");
598 if (!
IsHex(request.params[0].get_str())) {
600 "Pubkey must be a hex string");
602 std::vector<uint8_t> data(
ParseHex(request.params[0].get_str()));
603 CPubKey pubKey(data.begin(), data.end());
606 "Pubkey is not a valid public key");
612 std::set<CScript> script_pub_keys;
620 strLabel, script_pub_keys,
true ,
644 "Imports keys from a wallet dump file (see dumpwallet). Requires a "
645 "new wallet backup to include imported keys.\n"
646 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
654 "\nImport the wallet\n" +
656 "\nImport using the json rpc call\n" +
660 std::shared_ptr<CWallet>
const wallet =
675 "Importing wallets is disabled when blocks are pruned");
681 "Wallet is currently rescanning. Abort "
682 "existing rescan or wait.");
685 int64_t nTimeBegin = 0;
693 file.open(fs::u8path(request.params[0].get_str()),
694 std::ios::in | std::ios::ate);
695 if (!file.is_open()) {
697 "Cannot open wallet dump file");
703 int64_t nFilesize = std::max<int64_t>(1, file.tellg());
704 file.seekg(0, file.beg);
714 strprintf(
"%s " +
_(
"Importing...").translated,
717 std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
718 std::vector<std::pair<CScript, int64_t>> scripts;
719 while (file.good()) {
723 std::min<int>(50, 100 *
double(file.tellg()) /
727 std::getline(file, line);
728 if (line.empty() || line[0] ==
'#') {
732 std::vector<std::string> vstr;
733 boost::split(vstr, line, boost::is_any_of(
" "));
734 if (vstr.size() < 2) {
740 std::string strLabel;
742 for (
size_t nStr = 2; nStr < vstr.size(); nStr++) {
743 if (vstr[nStr].front() ==
'#') {
746 if (vstr[nStr] ==
"change=1") {
749 if (vstr[nStr] ==
"reserve=1") {
752 if (vstr[nStr].substr(0, 6) ==
"label=") {
759 std::make_tuple(key, nTime, fLabel, strLabel));
760 }
else if (
IsHex(vstr[0])) {
761 std::vector<uint8_t> vData(
ParseHex(vstr[0]));
765 std::pair<CScript, int64_t>(script, birth_time));
776 "Importing wallets is disabled when "
777 "private keys are disabled");
779 double total = double(keys.size() + scripts.size());
781 for (
const auto &key_tuple : keys) {
784 std::max(50, std::min<int>(75, 100 * progress / total) +
787 const CKey &key = std::get<0>(key_tuple);
788 int64_t time = std::get<1>(key_tuple);
789 bool has_label = std::get<2>(key_tuple);
790 std::string label = std::get<3>(key_tuple);
802 "Error importing key for %s\n",
813 nTimeBegin = std::min(nTimeBegin, time);
816 for (
const auto &script_pair : scripts) {
819 std::max(50, std::min<int>(75, 100 * progress / total) +
822 const CScript &script = script_pair.first;
823 int64_t time = script_pair.second;
832 nTimeBegin = std::min(nTimeBegin, time);
842 pwallet->chain().showProgress(
"", 100,
false);
844 pwallet->MarkDirty();
848 "Error adding some keys/scripts to wallet");
859 "Reveals the private key corresponding to 'address'.\n"
860 "Then the importprivkey can be used with this output\n",
863 "The bitcoin address for the private key"},
871 std::shared_ptr<CWallet>
const wallet =
885 std::string strAddress = request.params[0].get_str();
890 "Invalid Bitcoin address");
893 if (keyid.IsNull()) {
895 "Address does not refer to a key");
898 if (!spk_man.
GetKey(keyid, vchSecret)) {
900 "Private key for address " + strAddress +
911 "Dumps all wallet keys in a human-readable format to a server-side "
912 "file. This does not allow overwriting existing files.\n"
913 "Imported scripts are included in the dumpsfile, but corresponding "
914 "addresses may not be added automatically by importwallet.\n"
915 "Note that if your wallet contains keys which are not derived from "
916 "your HD seed (e.g. imported keys), these are not covered by\n"
917 "only backing up the seed itself, and must be backed up too (e.g. "
918 "ensure you back up the whole dumpfile).\n",
921 "The filename with path (absolute path recommended)"},
928 "The filename with full absolute path"},
934 std::shared_ptr<CWallet>
const pwallet =
947 wallet.BlockUntilSyncedToCurrentChain();
953 fs::path filepath = fs::u8path(request.params[0].get_str());
964 filepath.u8string() +
965 " already exists. If you are "
966 "sure this is what you want, "
967 "move it out of the way first");
972 if (!file.is_open()) {
974 "Cannot open wallet dump file");
977 std::map<CKeyID, int64_t> mapKeyBirth;
978 wallet.GetKeyBirthTimes(mapKeyBirth);
980 int64_t block_time = 0;
990 const std::map<CKeyID, int64_t> &mapKeyPool =
992 std::set<CScriptID> scripts = spk_man.
GetCScripts();
995 std::vector<std::pair<int64_t, CKeyID>> vKeyBirth;
996 for (
const auto &entry : mapKeyBirth) {
997 vKeyBirth.push_back(std::make_pair(entry.second, entry.first));
1000 std::sort(vKeyBirth.begin(), vKeyBirth.end());
1005 file <<
strprintf(
"# * Created on %s\n",
1007 file <<
strprintf(
"# * Best block at time of backup was %i (%s),\n",
1008 wallet.GetLastBlockHeight(),
1009 wallet.GetLastBlockHash().ToString());
1018 if (spk_man.
GetKey(seed_id, seed)) {
1022 file <<
"# extended private masterkey: "
1026 for (std::vector<std::pair<int64_t, CKeyID>>::const_iterator it =
1028 it != vKeyBirth.end(); it++) {
1029 const CKeyID &keyid = it->second;
1031 std::string strAddr;
1032 std::string strLabel;
1034 if (spk_man.
GetKey(keyid, key)) {
1037 keyid, strAddr, strLabel)) {
1038 file <<
strprintf(
"label=%s", strLabel);
1039 }
else if (keyid == seed_id) {
1041 }
else if (mapKeyPool.count(keyid)) {
1042 file <<
"reserve=1";
1043 }
else if (spk_man.mapKeyMetadata[keyid].hdKeypath ==
"s") {
1044 file <<
"inactivehdseed=1";
1049 " # addr=%s%s\n", strAddr,
1050 (spk_man.mapKeyMetadata[keyid].has_key_origin
1058 for (
const CScriptID &scriptid : scripts) {
1060 std::string create_time =
"0";
1061 std::string address =
1064 auto it = spk_man.m_script_metadata.find(scriptid);
1065 if (it != spk_man.m_script_metadata.end()) {
1071 file <<
strprintf(
" # addr=%s\n", address);
1075 file <<
"# End of dump\n";
1079 reply.
pushKV(
"filename", filepath.u8string());
1089 "dump all the UTXO tracked by the wallet.\n",
1098 "The list of UTXO corresponding to this address.",
1105 "The transaction id"},
1109 "The output's amount"},
1118 std::shared_ptr<CWallet>
const pwallet =
1129 wallet.BlockUntilSyncedToCurrentChain();
1138 for (
const auto &o : p.second) {
1140 utxo.
pushKV(
"txid", o.tx->GetId().ToString());
1141 utxo.
pushKV(
"vout", o.i);
1142 utxo.
pushKV(
"depth", o.nDepth);
1143 utxo.
pushKV(
"value", o.tx->tx->vout[o.i].nValue);
1183 std::vector<std::vector<uint8_t>> solverdata;
1186 switch (script_type) {
1188 CPubKey pubkey(solverdata[0].begin(), solverdata[0].end());
1200 "Trying to nest P2SH inside another P2SH");
1208 return "missing redeemscript";
1211 return "redeemScript does not match the scriptPubKey";
1218 for (
size_t i = 1; i + 1 < solverdata.size(); ++i) {
1219 CPubKey pubkey(solverdata[i].begin(), solverdata[i].end());
1225 return "unspendable script";
1228 return "unrecognized script";
1234 std::map<CKeyID, CPubKey> &pubkey_map, std::map<CKeyID, CKey> &privkey_map,
1235 std::set<CScript> &script_pub_keys,
bool &have_solving_data,
1236 const UniValue &data, std::vector<CKeyID> &ordered_pubkeys) {
1241 const UniValue &scriptPubKey = data[
"scriptPubKey"];
1244 scriptPubKey.
exists(
"address"))) {
1246 "scriptPubKey must be string with script or JSON "
1247 "with address string");
1249 const std::string &output =
1250 isScript ? scriptPubKey.
get_str() : scriptPubKey[
"address"].
get_str();
1253 const std::string &strRedeemScript =
1254 data.
exists(
"redeemscript") ? data[
"redeemscript"].
get_str() :
"";
1259 const bool internal =
1261 const bool watchOnly =
1264 if (data.
exists(
"range")) {
1267 "Range should not be specified for a non-descriptor import");
1277 "Invalid address \"" + output +
"\"");
1281 if (!
IsHex(output)) {
1283 "Invalid scriptPubKey \"" + output +
"\"");
1285 std::vector<uint8_t> vData(
ParseHex(output));
1286 script =
CScript(vData.begin(), vData.end());
1290 "Internal must be set to true for "
1291 "nonstandard scriptPubKey imports.");
1294 script_pub_keys.emplace(script);
1297 if (strRedeemScript.size()) {
1298 if (!
IsHex(strRedeemScript)) {
1300 "Invalid redeem script \"" + strRedeemScript +
1301 "\": must be hex string");
1303 auto parsed_redeemscript =
ParseHex(strRedeemScript);
1305 parsed_redeemscript.begin(), parsed_redeemscript.end());
1307 for (
size_t i = 0; i < pubKeys.
size(); ++i) {
1308 const auto &str = pubKeys[i].
get_str();
1311 "Pubkey \"" + str +
"\" must be a hex string");
1313 auto parsed_pubkey =
ParseHex(str);
1314 CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end());
1318 "\" is not a valid public key");
1320 pubkey_map.emplace(pubkey.
GetID(), pubkey);
1321 ordered_pubkeys.push_back(pubkey.
GetID());
1323 for (
size_t i = 0; i < keys.
size(); ++i) {
1324 const auto &str = keys[i].
get_str();
1328 "Invalid private key encoding");
1332 if (pubkey_map.count(
id)) {
1333 pubkey_map.erase(
id);
1335 privkey_map.emplace(
id, key);
1340 import_data.
redeemscript || pubkey_map.size() || privkey_map.size();
1341 if (have_solving_data) {
1347 bool spendable = std::all_of(
1349 [&](
const std::pair<CKeyID, bool> &used_key) {
1350 return privkey_map.count(used_key.first) > 0;
1352 if (!watchOnly && !spendable) {
1353 warnings.
push_back(
"Some private keys are missing, outputs "
1354 "will be considered watchonly. If this is "
1355 "intentional, specify the watchonly flag.");
1357 if (watchOnly && spendable) {
1359 "All private keys are provided, outputs will be considered "
1360 "spendable. If this is intentional, do not specify the "
1365 if (
error.empty()) {
1366 for (
const auto &require_key : import_data.
used_keys) {
1367 if (!require_key.second) {
1372 if (pubkey_map.count(require_key.first) == 0 &&
1373 privkey_map.count(require_key.first) == 0) {
1374 error =
"some required keys are missing";
1379 if (!
error.empty()) {
1381 ". If this is intentional, don't provide "
1382 "any keys, pubkeys or redeemscript.");
1385 privkey_map.clear();
1386 have_solving_data =
false;
1393 "Ignoring redeemscript as this is not a P2SH script.");
1395 for (
auto it = privkey_map.begin(); it != privkey_map.end();) {
1397 if (import_data.
used_keys.count(oldit->first) == 0) {
1398 warnings.
push_back(
"Ignoring irrelevant private key.");
1399 privkey_map.erase(oldit);
1402 for (
auto it = pubkey_map.begin(); it != pubkey_map.end();) {
1404 auto key_data_it = import_data.
used_keys.find(oldit->first);
1405 if (key_data_it == import_data.
used_keys.end() ||
1406 !key_data_it->second) {
1407 warnings.
push_back(
"Ignoring public key \"" +
1409 "\" as it doesn't appear inside P2PKH.");
1410 pubkey_map.erase(oldit);
1420 std::map<CKeyID, CPubKey> &pubkey_map,
1421 std::map<CKeyID, CKey> &privkey_map,
1422 std::set<CScript> &script_pub_keys,
1423 bool &have_solving_data,
1425 std::vector<CKeyID> &ordered_pubkeys) {
1428 const std::string &descriptor = data[
"desc"].
get_str();
1437 have_solving_data = parsed_desc->IsSolvable();
1438 const bool watch_only =
1441 int64_t range_start = 0, range_end = 0;
1442 if (!parsed_desc->IsRange() && data.
exists(
"range")) {
1445 "Range should not be specified for an un-ranged descriptor");
1446 }
else if (parsed_desc->IsRange()) {
1447 if (!data.
exists(
"range")) {
1450 "Descriptor is ranged, please specify the range");
1460 for (
int i = range_start; i <= range_end; ++i) {
1462 std::vector<CScript> scripts_temp;
1463 parsed_desc->Expand(i, keys, scripts_temp, out_keys);
1464 std::copy(scripts_temp.begin(), scripts_temp.end(),
1465 std::inserter(script_pub_keys, script_pub_keys.end()));
1466 for (
const auto &key_pair : out_keys.
pubkeys) {
1467 ordered_pubkeys.push_back(key_pair.first);
1470 for (
const auto &x : out_keys.
scripts) {
1474 parsed_desc->ExpandPrivate(i, keys, out_keys);
1477 std::inserter(pubkey_map, pubkey_map.end()));
1478 std::copy(out_keys.
keys.begin(), out_keys.
keys.end(),
1479 std::inserter(privkey_map, privkey_map.end()));
1484 for (
size_t i = 0; i < priv_keys.
size(); ++i) {
1485 const auto &str = priv_keys[i].
get_str();
1489 "Invalid private key encoding");
1496 if (!pubkey_map.count(
id)) {
1497 warnings.
push_back(
"Ignoring irrelevant private key.");
1499 privkey_map.emplace(
id, key);
1510 std::all_of(pubkey_map.begin(), pubkey_map.end(),
1511 [&](
const std::pair<CKeyID, CPubKey> &used_key) {
1512 return privkey_map.count(used_key.first) > 0;
1516 [&](
const std::pair<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>
1517 &entry) { return privkey_map.count(entry.first) > 0; });
1518 if (!watch_only && !spendable) {
1520 "Some private keys are missing, outputs will be considered "
1521 "watchonly. If this is intentional, specify the watchonly flag.");
1523 if (watch_only && spendable) {
1524 warnings.
push_back(
"All private keys are provided, outputs will be "
1525 "considered spendable. If this is intentional, do "
1526 "not specify the watchonly flag.");
1533 const int64_t timestamp)
1539 const bool internal =
1540 data.exists(
"internal") ? data[
"internal"].get_bool() :
false;
1542 if (
internal && data.exists(
"label")) {
1544 "Internal addresses should not have a label");
1546 const std::string &label =
1547 data.exists(
"label") ? data[
"label"].get_str() :
"";
1548 const bool add_keypool =
1549 data.exists(
"keypool") ? data[
"keypool"].get_bool() :
false;
1555 "Keys can only be imported to the keypool when "
1556 "private keys are disabled");
1560 std::map<CKeyID, CPubKey> pubkey_map;
1561 std::map<CKeyID, CKey> privkey_map;
1562 std::set<CScript> script_pub_keys;
1563 std::vector<CKeyID> ordered_pubkeys;
1564 bool have_solving_data;
1566 if (data.exists(
"scriptPubKey") && data.exists(
"desc")) {
1569 "Both a descriptor and a scriptPubKey should not be provided.");
1570 }
else if (data.exists(
"scriptPubKey")) {
1572 pwallet, import_data, pubkey_map, privkey_map, script_pub_keys,
1573 have_solving_data, data, ordered_pubkeys);
1574 }
else if (data.exists(
"desc")) {
1576 import_data, pubkey_map, privkey_map, script_pub_keys,
1577 have_solving_data, data, ordered_pubkeys);
1581 "Either a descriptor or scriptPubKey must be provided.");
1587 !privkey_map.empty()) {
1589 "Cannot import private keys to a wallet with "
1590 "private keys disabled");
1594 for (
const CScript &script : script_pub_keys) {
1597 "The wallet already contains the private "
1598 "key for this address or script (\"" +
1604 pwallet->MarkDirty();
1605 if (!pwallet->ImportScripts(import_data.
import_scripts, timestamp)) {
1607 "Error adding script to wallet");
1609 if (!pwallet->ImportPrivKeys(privkey_map, timestamp)) {
1612 if (!pwallet->ImportPubKeys(ordered_pubkeys, pubkey_map,
1614 internal, timestamp)) {
1616 "Error adding address to wallet");
1618 if (!pwallet->ImportScriptPubKeys(label, script_pub_keys,
1619 have_solving_data, !
internal,
1622 "Error adding address to wallet");
1628 result.
pushKV(
"error", e);
1635 if (warnings.
size()) {
1636 result.
pushKV(
"warnings", warnings);
1642 if (data.
exists(
"timestamp")) {
1643 const UniValue ×tamp = data[
"timestamp"];
1644 if (timestamp.
isNum()) {
1646 }
else if (timestamp.
isStr() && timestamp.
get_str() ==
"now") {
1650 strprintf(
"Expected number or \"now\" timestamp "
1651 "value for key. got type %s",
1655 "Missing required timestamp field for key");
1659 const int64_t objectTimestamp,
1660 const int64_t blockTimestamp) {
1662 "Rescan failed for %s with creation timestamp %d. There was an error "
1663 "reading a block from time %d, which is after or within %d seconds of "
1664 "key creation, and could contain transactions pertaining to the %s. As "
1665 "a result, transactions and coins using this %s may not appear in "
1666 "the wallet. This error could be caused by pruning or data corruption "
1667 "(see bitcoind log for details) and could be dealt with by downloading "
1668 "and rescanning the relevant blocks (see -reindex and -rescan "
1677 "Import addresses/scripts (with private or public keys, redeem "
1678 "script (P2SH)), optionally rescanning the blockchain from the "
1679 "earliest creation time of the imported scripts. Requires a new wallet "
1681 "If an address/script is imported without all of the private keys "
1682 "required to spend from that address, it will be watchonly. The "
1683 "'watchonly' option must be set to true in this case or a warning will "
1685 "Conversely, if all the private keys are provided and the "
1686 "address/script is spendable, the watchonly option must be set to "
1687 "false, or a warning will be returned.\n"
1688 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
1693 "Data to be imported",
1702 "Descriptor to import. If using descriptor, do not "
1703 "also provide address/scriptPubKey, scripts, or "
1708 "Type of scriptPubKey (string for script, json for "
1709 "address). Should not be provided if using a "
1712 {
"\"<script>\" | { \"address\":\"<address>\" }",
1717 "Creation time of the key expressed in " +
1721 " or the string \"now\" to "
1722 "substitute the current synced blockchain time. "
1724 "timestamp of the oldest\n"
1726 " key will determine how far "
1728 "blockchain rescans need to begin for missing "
1732 " \"now\" can be specified to "
1733 "bypass scanning, for keys which are known to "
1735 "have been used, and\n"
1737 " 0 can be specified to scan "
1739 "entire blockchain. Blocks up to 2 hours before "
1743 " creation time of all keys "
1745 "imported by the importmulti call will be "
1748 {
"timestamp | \"now\"",
"integer / string"}},
1751 "Allowed only if the scriptPubKey is a P2SH "
1752 "address/scriptPubKey"},
1756 "Array of strings giving pubkeys to import. They "
1757 "must occur in P2PKH scripts. They are not required "
1758 "when the private key is also provided (see the "
1759 "\"keys\" argument).",
1767 "Array of strings giving private keys to import. The "
1768 "corresponding public keys must occur in the output "
1776 "If a ranged descriptor is used, this specifies the "
1777 "end or the range (in the form [begin,end]) to "
1781 "Stating whether matching outputs should be treated "
1782 "as not incoming payments (also known as change)"},
1785 "Stating whether matching outputs should be "
1786 "considered watchonly."},
1788 "Label to assign to the address, only allowed with "
1791 "Stating whether imported public keys should be "
1792 "added to the keypool for when users request new "
1793 "addresses. Only allowed when wallet private keys "
1805 "Stating if should rescan the blockchain after all imports"},
1811 "Response is an array with the same size as the input that "
1812 "has the execution result",
1838 "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, "
1839 "\"timestamp\":1455191478 }, "
1840 "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" "
1842 "\"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1845 "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, "
1846 "\"timestamp\":1455191478 }]' '{ \"rescan\": false}'")
1851 std::shared_ptr<CWallet>
const wallet =
1858 RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
1862 const UniValue &requests = mainRequest.params[0];
1865 bool fRescan =
true;
1867 if (!mainRequest.params[1].isNull()) {
1868 const UniValue &options = mainRequest.params[1];
1870 if (options.
exists(
"rescan")) {
1871 fRescan = options[
"rescan"].
get_bool();
1876 if (fRescan && !reserver.
reserve()) {
1878 "Wallet is currently rescanning. Abort "
1879 "existing rescan or wait.");
1883 bool fRunScan =
false;
1884 int64_t nLowestTimestamp = 0;
1893 FoundBlock().time(nLowestTimestamp).mtpTime(now)));
1898 const int64_t minimumTimestamp = 1;
1901 const int64_t timestamp = std::max(
1912 if (result[
"success"].get_bool()) {
1917 if (timestamp < nLowestTimestamp) {
1918 nLowestTimestamp = timestamp;
1922 if (fRescan && fRunScan && requests.
size()) {
1924 nLowestTimestamp, reserver,
true );
1932 "Rescan aborted by user.");
1934 if (scannedTime > nLowestTimestamp) {
1935 std::vector<UniValue> results =
response.getValues();
1945 results.at(i).exists(
"error")) {
1957 response.push_back(std::move(result));
1971 const int64_t timestamp)
1977 if (!data.exists(
"desc")) {
1981 const std::string &descriptor = data[
"desc"].get_str();
1983 data.exists(
"active") ? data[
"active"].get_bool() :
false;
1984 const bool internal =
1985 data.exists(
"internal") ? data[
"internal"].get_bool() :
false;
1986 const std::string &label =
1987 data.exists(
"label") ? data[
"label"].get_str() :
"";
1999 int64_t range_start = 0, range_end = 1, next_index = 0;
2000 if (!parsed_desc->IsRange() && data.exists(
"range")) {
2003 "Range should not be specified for an un-ranged descriptor");
2004 }
else if (parsed_desc->IsRange()) {
2005 if (data.exists(
"range")) {
2007 range_start = range.first;
2010 range_end = range.second + 1;
2013 "Range not given, using default keypool range");
2017 next_index = range_start;
2019 if (data.exists(
"next_index")) {
2020 next_index = data[
"next_index"].get_int64();
2022 if (next_index < range_start || next_index >= range_end) {
2024 "next_index is out of range");
2030 if (active && !parsed_desc->IsRange()) {
2032 "Active descriptors must be ranged");
2036 if (data.exists(
"range") && data.exists(
"label")) {
2038 "Ranged descriptors should not have a label");
2042 if (
internal && data.exists(
"label")) {
2044 "Internal addresses should not have a label");
2048 if (active && !parsed_desc->IsSingleType()) {
2050 "Combo descriptors cannot be set to active");
2055 !keys.
keys.empty()) {
2057 "Cannot import private keys to a wallet with "
2058 "private keys disabled");
2064 std::vector<CScript> scripts;
2065 if (!parsed_desc->Expand(0, keys, scripts, expand_keys)) {
2068 "Cannot expand descriptor. Probably because of hardened "
2069 "derivations without private keys provided");
2071 parsed_desc->ExpandPrivate(0, keys, expand_keys);
2074 bool have_all_privkeys = !expand_keys.
keys.empty();
2075 for (
const auto &entry : expand_keys.
origins) {
2076 const CKeyID &key_id = entry.first;
2078 if (!expand_keys.
GetKey(key_id, key)) {
2079 have_all_privkeys =
false;
2086 if (keys.
keys.empty()) {
2089 "Cannot import descriptor without private keys to a wallet "
2090 "with private keys enabled");
2092 if (!have_all_privkeys) {
2094 "Not all private keys provided. Some wallet functionality "
2095 "may return unexpected errors");
2100 range_end, next_index);
2103 auto existing_spk_manager =
2104 pwallet->GetDescriptorScriptPubKeyMan(w_desc);
2105 if (existing_spk_manager) {
2106 LOCK(existing_spk_manager->cs_desc_man);
2108 existing_spk_manager->GetWalletDescriptor().range_start) {
2112 "range_start can only decrease; current range = "
2114 existing_spk_manager->GetWalletDescriptor().range_start,
2115 existing_spk_manager->GetWalletDescriptor().range_end));
2121 pwallet->AddWalletDescriptor(w_desc, keys, label,
internal);
2122 if (spk_manager ==
nullptr) {
2125 strprintf(
"Could not add descriptor '%s'", descriptor));
2132 "Unknown output type, cannot set descriptor to active.");
2134 pwallet->AddActiveScriptPubKeyMan(
2135 spk_manager->GetID(), *w_desc.
descriptor->GetOutputType(),
2143 result.
pushKV(
"error", e);
2150 if (warnings.
size()) {
2151 result.
pushKV(
"warnings", warnings);
2158 "importdescriptors",
2159 "Import descriptors. This will trigger a rescan of the blockchain "
2160 "based on the earliest timestamp of all descriptors being imported. "
2161 "Requires a new wallet backup.\n"
2162 "\nNote: This call can take over an hour to complete if using an early "
2163 "timestamp; during that time, other rpc calls\n"
2164 "may report that the imported keys, addresses or scripts exist but "
2165 "related transactions are still missing.\n",
2170 "Data to be imported",
2179 "Descriptor to import."},
2181 "Set this descriptor to be the active descriptor for "
2182 "the corresponding output type/externality"},
2185 "If a ranged descriptor is used, this specifies the "
2186 "end or the range (in the form [begin,end]) to "
2190 "If a ranged descriptor is set to active, this "
2191 "specifies the next index to generate addresses "
2196 "Time from which to start rescanning the blockchain "
2197 "for this descriptor, in " +
2201 " Use the string \"now\" to "
2202 "substitute the current synced blockchain time.\n"
2204 " \"now\" can be specified to "
2205 "bypass scanning, for outputs which are known to "
2206 "never have been used, and\n"
2208 " 0 can be specified to scan the "
2209 "entire blockchain. Blocks up to 2 hours before "
2210 "the earliest timestamp\n"
2212 " of all descriptors being imported "
2215 {
"timestamp | \"now\"",
"integer / string"}},
2217 "Whether matching outputs should be treated as not "
2218 "incoming payments (e.g. change)"},
2220 "Label to assign to the address, only allowed with "
2229 "Response is an array with the same size as the input that "
2230 "has the execution result",
2255 "'[{ \"desc\": \"<my descriptor>\", "
2256 "\"timestamp\":1455191478, \"internal\": true }, "
2257 "{ \"desc\": \"<my desccriptor 2>\", \"label\": "
2258 "\"example 2\", \"timestamp\": 1455191480 }]'") +
2260 "importdescriptors",
2261 "'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, "
2262 "\"active\": true, \"range\": [0,100], \"label\": \"<my "
2263 "cashaddr wallet>\" }]'")},
2266 std::shared_ptr<CWallet>
const wallet =
2276 "importdescriptors is not available for "
2277 "non-descriptor wallets");
2280 RPCTypeCheck(main_request.params, {UniValue::VARR, UniValue::VOBJ});
2285 "Wallet is currently rescanning. Abort "
2286 "existing rescan or wait.");
2289 const UniValue &requests = main_request.params[0];
2290 const int64_t minimum_timestamp = 1;
2292 int64_t lowest_timestamp = 0;
2293 bool rescan =
false;
2301 FoundBlock().time(lowest_timestamp).mtpTime(now)));
2306 const int64_t timestamp = std::max(
2312 if (lowest_timestamp > timestamp) {
2313 lowest_timestamp = timestamp;
2318 if (!rescan && result[
"success"].get_bool()) {
2328 lowest_timestamp, reserver,
true );
2336 "Rescan aborted by user.");
2339 if (scanned_time > lowest_timestamp) {
2340 std::vector<UniValue> results =
response.getValues();
2345 for (
unsigned int i = 0; i < requests.
size(); ++i) {
2354 results.at(i).exists(
"error")) {
2367 response.push_back(std::move(result));
2381 "Safely copies current wallet file to destination, which can be a "
2382 "directory or a path with filename.\n",
2385 "The destination directory or file"},
2392 std::shared_ptr<CWallet>
const wallet =
2402 pwallet->BlockUntilSyncedToCurrentChain();
2406 std::string strDest = request.params[0].get_str();
2409 "Error: Wallet backup failed!");
2420 "\nRestore and loads a wallet from backup.\n",
2423 "The name that will be applied to the restored wallet"},
2425 "The backup file that will be used to restore the wallet."},
2428 "Save wallet name to persistent settings and load on startup. "
2429 "True to add wallet to startup list, false to remove, null to "
2430 "leave unchanged."},
2437 "The wallet name if restored successfully."},
2439 "Warning message if wallet was not loaded cleanly."},
2443 "\"testwallet\" \"home\\backups\\backup-file.bak\"") +
2446 "\"testwallet\" \"home\\backups\\backup-file.bak\"") +
2449 {{
"wallet_name",
"testwallet"},
2450 {
"backup_file",
"home\\backups\\backup-file.bak\""},
2451 {
"load_on_startup",
true}}) +
2454 {{
"wallet_name",
"testwallet"},
2455 {
"backup_file",
"home\\backups\\backup-file.bak\""},
2456 {
"load_on_startup",
true}})},
2466 "Backup file does not exist");
2469 std::string wallet_name = request.params[0].get_str();
2476 "Wallet name already exists.");
2481 strprintf(
"Failed to create database path "
2482 "'%s'. Database already exists.",
2486 auto wallet_file = wallet_path /
"wallet.dat";
2488 fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
2490 auto [
wallet, warnings] =
static RPCHelpMan dumpcoins()
RPCHelpMan importprivkey()
static const int64_t TIMESTAMP_MIN
RPCHelpMan importdescriptors()
static void RescanWallet(CWallet &wallet, const WalletRescanReserver &reserver, int64_t time_begin=TIMESTAMP_MIN, bool update=true)
static std::string RecurseImportData(const CScript &script, ImportData &import_data, const ScriptContext script_ctx)
RPCHelpMan importaddress()
RPCHelpMan importwallet()
static UniValue ProcessImportLegacy(CWallet *const pwallet, ImportData &import_data, std::map< CKeyID, CPubKey > &pubkey_map, std::map< CKeyID, CKey > &privkey_map, std::set< CScript > &script_pub_keys, bool &have_solving_data, const UniValue &data, std::vector< CKeyID > &ordered_pubkeys)
RPCHelpMan importpubkey()
static std::string EncodeDumpString(const std::string &str)
static bool GetWalletAddressesForKey(const Config &config, LegacyScriptPubKeyMan *spk_man, const CWallet *const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
static std::string DecodeDumpString(const std::string &str)
RPCHelpMan importprunedfunds()
Span< const CRPCCommand > GetWalletDumpRPCCommands()
RPCHelpMan restorewallet()
static UniValue ProcessImportDescriptor(ImportData &import_data, std::map< CKeyID, CPubKey > &pubkey_map, std::map< CKeyID, CKey > &privkey_map, std::set< CScript > &script_pub_keys, bool &have_solving_data, const UniValue &data, std::vector< CKeyID > &ordered_pubkeys)
@ TOP
Top-level scriptPubKey.
static UniValue ProcessImport(CWallet *const pwallet, const UniValue &data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
RPCHelpMan backupwallet()
static UniValue ProcessDescriptorImport(CWallet *const pwallet, const UniValue &data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet -> cs_wallet)
RPCHelpMan removeprunedfunds()
static int64_t GetImportTimestamp(const UniValue &data, int64_t now)
static std::string GetRescanErrorMessage(const std::string &object, const int64_t objectTimestamp, const int64_t blockTimestamp)
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath)
Write HD keypaths as strings.
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define CHECK_NONFATAL(condition)
Identity function.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Double ended buffer combining vector and stream-like interfaces.
CKeyID seed_id
seed hash160
An encapsulated secp256k1 private key.
const uint8_t * begin() const
unsigned int size() const
Simple read-only vector-like interface.
bool IsValid() const
Check whether this private key is valid.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
A reference to a CKey: the Hash160 of its serialized public key.
Used to create a Merkle proof (usually from a subset of transactions), which consists of a block head...
CBlockHeader header
Public only for unit testing.
A mutable version of CTransaction.
TxId GetId() const
Compute the id and hash of this CMutableTransaction.
uint256 ExtractMatches(std::vector< uint256 > &vMatch, std::vector< size_t > &vnIndex)
Extract the matching txid's represented by this partial merkle tree and their respective indices with...
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization (see script.h)
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
BlockHash GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
void ConnectScriptPubKeyManNotifiers()
Connect the signals from ScriptPubKeyMans to the signals in CWallet.
const std::string GetDisplayName() const override
Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet ha...
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
bool IsAbortingRescan() const
interfaces::Chain & chain() const
Interface for accessing chain state.
bool BackupWallet(const std::string &strDest) const
const CAddressBookData * FindAddressBookEntry(const CTxDestination &, bool allow_change=false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
virtual std::set< CScriptID > GetCScripts() const
RecursiveMutex cs_KeyStore
const CHDChain & GetHDChain() const
bool GetKey(const CKeyID &address, CKey &keyOut) const override
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
A Span is an object that can refer to a contiguous sequence of objects.
const std::string & get_str() const
enum VType getType() const
int64_t get_int64() const
const std::vector< UniValue > & getValues() const
bool push_back(const UniValue &val)
const UniValue & get_array() const
bool exists(const std::string &key) const
bool pushKV(const std::string &key, const UniValue &val)
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
virtual bool findAncestorByHash(const BlockHash &block_hash, const BlockHash &ancestor_hash, const FoundBlock &ancestor_out={})=0
Return whether block descends from a specified ancestor, and optionally return ancestor information.
virtual bool findBlock(const BlockHash &hash, const FoundBlock &block={})=0
Return whether node has the block and optionally return block metadata or contents.
virtual void showProgress(const std::string &title, int progress, bool resume_possible)=0
Send progress indicator.
virtual bool havePruned()=0
Check if any block has been pruned.
Helper for findBlock to selectively return pieces of block data.
const std::string CLIENT_BUILD
const std::string CLIENT_NAME
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
DBErrors ZapSelectTx(std::vector< TxId > &txIdsIn, std::vector< TxId > &txIdsOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportPubKeys(const std::vector< CKeyID > &ordered_pubkeys, const std::map< CKeyID, CPubKey > &pubkey_map, const std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo >> &key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportScripts(const std::set< CScript > scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
bool ImportPrivKeys(const std::map< CKeyID, CKey > &privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
isminetype IsMine(const CTxDestination &dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool ImportScriptPubKeys(const std::string &label, const std::set< CScript > &script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
const CChainParams & GetChainParams() const override
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
bool IsWalletFlagSet(uint64_t flag) const override
Check if a certain wallet flag is set.
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver &reserver, bool update)
Scan active chain for relevant transactions after importing keys.
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
std::string EncodeExtKey(const CExtKey &key)
std::string EncodeSecret(const CKey &key)
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
CKey DecodeSecret(const std::string &str)
static path absolute(const path &p)
static bool exists(const path &p)
static bool copy_file(const path &from, const path &to, copy_options options)
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
std::vector< CTxDestination > GetAllDestinationsForKey(const CPubKey &key)
Get all destinations (potentially) supported by the wallet for the given key.
static CTransactionRef MakeTransactionRef()
std::shared_ptr< const CTransaction > CTransactionRef
UniValue JSONRPCError(int code, const std::string &message)
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_WALLET_ERROR
Wallet errors Unspecified problem with wallet (key not found etc.)
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
std::pair< int64_t, int64_t > ParseDescriptorRange(const UniValue &value)
Parse a JSON range specified as int64, or [int64, int64].
std::vector< uint8_t > ParseHexV(const UniValue &v, std::string strName)
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
std::vector< uint8_t > ParseHex(const char *psz)
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
void SetSeed(const uint8_t *seed, unsigned int nSeedLen)
Confirmation includes tx status and a triplet of {block height/block hash/tx index in block} at which...
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
bool GetKey(const CKeyID &keyid, CKey &key) const override
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
std::unique_ptr< CScript > redeemscript
Provided redeemScript; will be moved to import_scripts if relevant.
std::map< CKeyID, bool > used_keys
Import these private keys if available (the value indicates whether if the key is required for solvab...
std::set< CScript > import_scripts
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > key_origins
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ STR_HEX
Special type that is a STR with only hex chars.
@ OMITTED_NAMED_ARG
Optional arg that is a named argument and has a default value of null.
@ OMITTED
Optional argument with default value omitted because they are implicitly clear.
@ ELISION
Special type to denote elision (...)
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
A TxId is the identifier of a transaction.
WalletContext struct containing references to state shared between CWallet instances,...
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
bool error(const char *fmt, const Args &...args)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t ParseISO8601DateTime(const std::string &str)
T GetTime()
Return system time (or mocked time, if set)
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
const char * uvTypeName(UniValue::VType t)
const UniValue NullUniValue
static const int PROTOCOL_VERSION
network protocol versioning
void EnsureWalletIsUnlocked(const CWallet *pwallet)
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
WalletContext & EnsureWalletContext(const std::any &context)
std::tuple< std::shared_ptr< CWallet >, std::vector< bilingual_str > > LoadWalletHelper(WalletContext &context, UniValue load_on_start_param, const std::string wallet_name)
fs::path GetWalletDir()
Get the path of the wallet directory.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.