39 std::stringstream
ret;
40 for (
const unsigned char c : str) {
41 if (c <= 32 || c >= 128 || c ==
'%') {
51 std::stringstream
ret;
52 for (
unsigned int pos = 0; pos < str.length(); pos++) {
53 unsigned char c = str[pos];
54 if (c ==
'%' && pos+2 < str.length()) {
55 c = (((str[pos+1]>>6)*9+((str[pos+1]-
'0')&15)) << 4) |
56 ((str[pos+2]>>6)*9+((str[pos+2]-
'0')&15));
66 bool fLabelFound =
false;
68 spk_man->GetKey(keyid, key);
70 const auto* address_book_entry =
wallet.FindAddressBookEntry(dest);
71 if (address_book_entry) {
72 if (!strAddr.empty()) {
90 int64_t scanned_time =
wallet.RescanFromTime(time_begin, reserver, update);
91 if (
wallet.IsAbortingRescan()) {
93 }
else if (scanned_time > time_begin) {
100 auto& chain{
wallet.chain()};
101 if (!chain.havePruned()) {
109 if (found && !chain.hasBlocks(tip_hash, height)) {
117 "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
118 "Hint: use importmulti to import more than one private key.\n"
119 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
120 "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"
121 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
122 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
123 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
131 "\nDump a private key\n"
133 "\nImport the private key with rescan\n"
135 "\nImport using a label and without rescan\n"
136 +
HelpExampleCli(
"importprivkey",
"\"mykey\" \"testing\" false") +
137 "\nImport using default blank label and without rescan\n"
139 "\nAs a JSON-RPC call\n"
140 +
HelpExampleRpc(
"importprivkey",
"\"mykey\", \"testing\", false")
156 LOCK(pwallet->cs_wallet);
160 std::string strSecret = request.params[0].get_str();
164 if (!request.params[2].isNull())
165 fRescan = request.params[2].get_bool();
167 if (fRescan && pwallet->chain().havePruned()) {
174 if (fRescan && !reserver.
reserve()) {
185 pwallet->MarkDirty();
191 if (!request.params[1].isNull() || !pwallet->FindAddressBookEntry(dest)) {
192 pwallet->SetAddressBook(dest, strLabel,
"receive");
197 if (!pwallet->ImportPrivKeys({{vchAddress, key}}, 1)) {
219 "\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"
220 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
221 "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"
222 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
223 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
224 "If you have the full public key, you should call importpubkey instead of this.\n"
225 "Hint: use importmulti to import more than one address.\n"
226 "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
227 "as change, and not show up in many RPCs.\n"
228 "Note: Use \"getwalletinfo\" to query the scanning progress.\n"
229 "Note: This command is only compatible with legacy wallets. Use \"importdescriptors\" with \"addr(X)\" for descriptor wallets.\n",
238 "\nImport an address with rescan\n"
240 "\nImport using a label without rescan\n"
241 +
HelpExampleCli(
"importaddress",
"\"myaddress\" \"testing\" false") +
242 "\nAs a JSON-RPC call\n"
243 +
HelpExampleRpc(
"importaddress",
"\"myaddress\", \"testing\", false")
256 if (!request.params[2].isNull())
257 fRescan = request.params[2].get_bool();
259 if (fRescan && pwallet->chain().havePruned()) {
267 if (fRescan && !reserver.
reserve()) {
273 if (!request.params[3].isNull())
274 fP2SH = request.params[3].get_bool();
277 LOCK(pwallet->cs_wallet);
288 pwallet->MarkDirty();
291 }
else if (
IsHex(request.params[0].get_str())) {
292 std::vector<unsigned char> data(
ParseHex(request.params[0].get_str()));
293 CScript redeem_script(data.begin(), data.end());
295 std::set<CScript> scripts = {redeem_script};
296 pwallet->ImportScripts(scripts, 0);
302 pwallet->ImportScriptPubKeys(strLabel, scripts,
false,
true, 1);
310 pwallet->ResubmitWalletTransactions(
false,
true);
321 "\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",
334 if (!
DecodeHexTx(tx, request.params[0].get_str())) {
344 std::vector<uint256> vMatch;
345 std::vector<unsigned int> vIndex;
350 LOCK(pwallet->cs_wallet);
352 if (!pwallet->chain().findAncestorByHash(pwallet->GetLastBlockHash(), merkleBlock.
header.
GetHash(),
FoundBlock().height(height))) {
356 std::vector<uint256>::const_iterator it;
357 if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx)) == vMatch.end()) {
361 unsigned int txnIndex = vIndex[it - vMatch.begin()];
364 if (pwallet->IsMine(*tx_ref)) {
377 "\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",
383 HelpExampleCli(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
384 "\nAs a JSON-RPC call\n"
385 +
HelpExampleRpc(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
392 LOCK(pwallet->cs_wallet);
395 std::vector<uint256> vHash;
396 vHash.push_back(hash);
397 std::vector<uint256> vHashOut;
399 if (pwallet->ZapSelectTx(vHash, vHashOut) != DBErrors::LOAD_OK) {
403 if(vHashOut.empty()) {
415 "\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"
416 "Hint: use importmulti to import more than one public key.\n"
417 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
418 "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"
419 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
420 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
421 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
429 "\nImport a public key with rescan\n"
431 "\nImport using a label without rescan\n"
432 +
HelpExampleCli(
"importpubkey",
"\"mypubkey\" \"testing\" false") +
433 "\nAs a JSON-RPC call\n"
434 +
HelpExampleRpc(
"importpubkey",
"\"mypubkey\", \"testing\", false")
447 if (!request.params[2].isNull())
448 fRescan = request.params[2].get_bool();
450 if (fRescan && pwallet->chain().havePruned()) {
458 if (fRescan && !reserver.
reserve()) {
462 if (!
IsHex(request.params[0].get_str()))
464 std::vector<unsigned char> data(
ParseHex(request.params[0].get_str()));
470 LOCK(pwallet->cs_wallet);
472 std::set<CScript> script_pub_keys;
477 pwallet->MarkDirty();
479 pwallet->ImportScriptPubKeys(strLabel, script_pub_keys,
true,
true, 1);
481 pwallet->ImportPubKeys({pubKey.
GetID()}, {{pubKey.
GetID(), pubKey}} , {},
false,
false, 1);
486 pwallet->ResubmitWalletTransactions(
false,
true);
498 "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
499 "Note: Blockchain and Mempool will be rescanned after a successful import. Use \"getwalletinfo\" to query the scanning progress.\n",
505 "\nDump the wallet\n"
507 "\nImport the wallet\n"
509 "\nImport using the json rpc call\n"
524 int64_t nTimeBegin = 0;
527 LOCK(pwallet->cs_wallet);
532 file.open(
fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate);
533 if (!file.is_open()) {
538 int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
539 file.seekg(0, file.beg);
543 pwallet->chain().showProgress(
strprintf(
"%s " +
_(
"Importing…").translated, pwallet->GetDisplayName()), 0,
false);
544 std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
545 std::vector<std::pair<CScript, int64_t>> scripts;
546 while (file.good()) {
547 pwallet->chain().showProgress(
"", std::max(1, std::min(50, (
int)(((
double)file.tellg() / (
double)nFilesize) * 100))),
false);
549 std::getline(file, line);
550 if (line.empty() || line[0] ==
'#')
553 std::vector<std::string> vstr =
SplitString(line,
' ');
559 std::string strLabel;
561 for (
unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
562 if (vstr[nStr].front() ==
'#')
564 if (vstr[nStr] ==
"change=1")
566 if (vstr[nStr] ==
"reserve=1")
568 if (vstr[nStr].substr(0,6) ==
"label=") {
573 nTimeBegin = std::min(nTimeBegin, nTime);
574 keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
575 }
else if(
IsHex(vstr[0])) {
576 std::vector<unsigned char> vData(
ParseHex(vstr[0]));
579 if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
580 scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
587 pwallet->chain().showProgress(
"", 100,
false);
590 double total = (double)(keys.size() + scripts.size());
592 for (
const auto& key_tuple : keys) {
593 pwallet->chain().showProgress(
"", std::max(50, std::min(75, (
int)((progress / total) * 100) + 50)),
false);
594 const CKey& key = std::get<0>(key_tuple);
595 int64_t time = std::get<1>(key_tuple);
596 bool has_label = std::get<2>(key_tuple);
597 std::string label = std::get<3>(key_tuple);
605 if (!pwallet->ImportPrivKeys({{keyid, key}}, time)) {
612 pwallet->SetAddressBook(
PKHash(keyid), label,
"receive");
615 for (
const auto& script_pair : scripts) {
616 pwallet->chain().showProgress(
"", std::max(50, std::min(75, (
int)((progress / total) * 100) + 50)),
false);
617 const CScript& script = script_pair.first;
618 int64_t time = script_pair.second;
620 if (!pwallet->ImportScripts({script}, time)) {
621 pwallet->WalletLogPrintf(
"Error importing script %s\n",
HexStr(script));
628 pwallet->chain().showProgress(
"", 100,
false);
630 pwallet->chain().showProgress(
"", 100,
false);
632 pwallet->MarkDirty();
645 "\nReveals the private key corresponding to 'address'.\n"
646 "Then the importprivkey can be used with this output\n",
669 std::string strAddress = request.params[0].get_str();
675 if (keyid.IsNull()) {
679 if (!spk_man.
GetKey(keyid, vchSecret)) {
691 "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
692 "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n"
693 "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"
694 "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n",
718 wallet.BlockUntilSyncedToCurrentChain();
741 std::map<CKeyID, int64_t> mapKeyBirth;
742 wallet.GetKeyBirthTimes(mapKeyBirth);
744 int64_t block_time = 0;
752 std::set<CScriptID> scripts = spk_man.
GetCScripts();
755 std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
756 for (
const auto& entry : mapKeyBirth) {
757 vKeyBirth.push_back(std::make_pair(entry.second, entry.first));
760 std::sort(vKeyBirth.begin(), vKeyBirth.end());
765 file <<
strprintf(
"# * Best block at time of backup was %i (%s),\n",
wallet.GetLastBlockHeight(),
wallet.GetLastBlockHash().ToString());
774 if (spk_man.
GetKey(seed_id, seed)) {
778 file <<
"# extended private masterkey: " <<
EncodeExtKey(masterKey) <<
"\n\n";
781 for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
782 const CKeyID &keyid = it->second;
785 std::string strLabel;
787 if (spk_man.
GetKey(keyid, key)) {
789 const auto it{spk_man.mapKeyMetadata.find(keyid)};
790 if (it != spk_man.mapKeyMetadata.end()) metadata = it->second;
794 }
else if (keyid == seed_id) {
796 }
else if (mapKeyPool.count(keyid)) {
799 file <<
"inactivehdseed=1";
807 for (
const CScriptID &scriptid : scripts) {
809 std::string create_time =
"0";
812 auto it = spk_man.m_script_metadata.find(scriptid);
813 if (it != spk_man.m_script_metadata.end()) {
818 file <<
strprintf(
" # addr=%s\n", address);
822 file <<
"# End of dump\n";
857 std::vector<std::vector<unsigned char>> solverdata;
860 switch (script_type) {
877 if (!subscript)
return "missing redeemscript";
878 if (
CScriptID(*subscript) !=
id)
return "redeemScript does not match the scriptPubKey";
883 for (
size_t i = 1; i + 1< solverdata.size(); ++i) {
893 if (!subscript)
return "missing witnessscript";
894 if (
CScriptID(*subscript) !=
id)
return "witnessScript does not match the scriptPubKey or redeemScript";
895 if (script_ctx == ScriptContext::TOP) {
905 if (script_ctx == ScriptContext::TOP) {
911 return "unspendable script";
915 return "unrecognized script";
920 static UniValue ProcessImportLegacy(
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)
925 const UniValue& scriptPubKey = data[
"scriptPubKey"];
930 const std::string& output = isScript ? scriptPubKey.
get_str() : scriptPubKey[
"address"].
get_str();
933 const std::string& strRedeemScript = data.
exists(
"redeemscript") ? data[
"redeemscript"].
get_str() :
"";
934 const std::string& witness_script_hex = data.
exists(
"witnessscript") ? data[
"witnessscript"].
get_str() :
"";
937 const bool internal = data.
exists(
"internal") ? data[
"internal"].
get_bool() :
false;
938 const bool watchOnly = data.
exists(
"watchonly") ? data[
"watchonly"].
get_bool() :
false;
940 if (data.
exists(
"range")) {
956 if (!
IsHex(output)) {
959 std::vector<unsigned char> vData(
ParseHex(output));
960 script =
CScript(vData.begin(), vData.end());
966 script_pub_keys.emplace(script);
969 if (strRedeemScript.size()) {
970 if (!
IsHex(strRedeemScript)) {
973 auto parsed_redeemscript =
ParseHex(strRedeemScript);
974 import_data.
redeemscript = std::make_unique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end());
976 if (witness_script_hex.size()) {
977 if (!
IsHex(witness_script_hex)) {
980 auto parsed_witnessscript =
ParseHex(witness_script_hex);
981 import_data.
witnessscript = std::make_unique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
983 for (
size_t i = 0; i < pubKeys.
size(); ++i) {
984 const auto& str = pubKeys[i].
get_str();
993 pubkey_map.emplace(pubkey.
GetID(), pubkey);
994 ordered_pubkeys.push_back(pubkey.
GetID());
996 for (
size_t i = 0; i < keys.
size(); ++i) {
997 const auto& str = keys[i].
get_str();
1004 if (pubkey_map.count(
id)) {
1005 pubkey_map.erase(
id);
1007 privkey_map.emplace(
id, key);
1013 if (have_solving_data) {
1018 bool spendable = std::all_of(import_data.
used_keys.begin(), import_data.
used_keys.end(), [&](
const std::pair<CKeyID, bool>& used_key){ return privkey_map.count(used_key.first) > 0; });
1019 if (!watchOnly && !spendable) {
1020 warnings.
push_back(
"Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1022 if (watchOnly && spendable) {
1023 warnings.
push_back(
"All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1027 if (
error.empty()) {
1028 for (
const auto& require_key : import_data.
used_keys) {
1029 if (!require_key.second)
continue;
1030 if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) {
1031 error =
"some required keys are missing";
1036 if (!
error.empty()) {
1037 warnings.
push_back(
"Importing as non-solvable: " +
error +
". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.");
1040 privkey_map.clear();
1041 have_solving_data =
false;
1044 if (import_data.
redeemscript) warnings.
push_back(
"Ignoring redeemscript as this is not a P2SH script.");
1045 if (import_data.
witnessscript) warnings.
push_back(
"Ignoring witnessscript as this is not a (P2SH-)P2WSH script.");
1046 for (
auto it = privkey_map.begin(); it != privkey_map.end(); ) {
1048 if (import_data.
used_keys.count(oldit->first) == 0) {
1049 warnings.
push_back(
"Ignoring irrelevant private key.");
1050 privkey_map.erase(oldit);
1053 for (
auto it = pubkey_map.begin(); it != pubkey_map.end(); ) {
1055 auto key_data_it = import_data.
used_keys.find(oldit->first);
1056 if (key_data_it == import_data.
used_keys.end() || !key_data_it->second) {
1057 warnings.
push_back(
"Ignoring public key \"" +
HexStr(oldit->first) +
"\" as it doesn't appear inside P2PKH or P2WPKH.");
1058 pubkey_map.erase(oldit);
1067 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)
1071 const std::string& descriptor = data[
"desc"].
get_str();
1074 auto parsed_desc =
Parse(descriptor, keys,
error,
true);
1082 have_solving_data = parsed_desc->IsSolvable();
1083 const bool watch_only = data.
exists(
"watchonly") ? data[
"watchonly"].
get_bool() :
false;
1085 int64_t range_start = 0, range_end = 0;
1086 if (!parsed_desc->IsRange() && data.
exists(
"range")) {
1088 }
else if (parsed_desc->IsRange()) {
1089 if (!data.
exists(
"range")) {
1098 for (
int i = range_start; i <= range_end; ++i) {
1100 std::vector<CScript> scripts_temp;
1101 parsed_desc->Expand(i, keys, scripts_temp, out_keys);
1102 std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end()));
1103 for (
const auto& key_pair : out_keys.
pubkeys) {
1104 ordered_pubkeys.push_back(key_pair.first);
1107 for (
const auto& x : out_keys.
scripts) {
1111 parsed_desc->ExpandPrivate(i, keys, out_keys);
1113 std::copy(out_keys.
pubkeys.begin(), out_keys.
pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end()));
1114 std::copy(out_keys.
keys.begin(), out_keys.
keys.end(), std::inserter(privkey_map, privkey_map.end()));
1118 for (
size_t i = 0; i < priv_keys.
size(); ++i) {
1119 const auto& str = priv_keys[i].
get_str();
1128 if (!pubkey_map.count(
id)) {
1129 warnings.
push_back(
"Ignoring irrelevant private key.");
1131 privkey_map.emplace(
id, key);
1139 bool spendable = std::all_of(pubkey_map.begin(), pubkey_map.end(),
1140 [&](
const std::pair<CKeyID, CPubKey>& used_key) {
1141 return privkey_map.count(used_key.first) > 0;
1143 [&](
const std::pair<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& entry) {
1144 return privkey_map.count(entry.first) > 0;
1146 if (!watch_only && !spendable) {
1147 warnings.
push_back(
"Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1149 if (watch_only && spendable) {
1150 warnings.
push_back(
"All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1162 const bool internal = data.exists(
"internal") ? data[
"internal"].get_bool() :
false;
1164 if (
internal && data.exists(
"label")) {
1168 const bool add_keypool = data.exists(
"keypool") ? data[
"keypool"].get_bool() :
false;
1176 std::map<CKeyID, CPubKey> pubkey_map;
1177 std::map<CKeyID, CKey> privkey_map;
1178 std::set<CScript> script_pub_keys;
1179 std::vector<CKeyID> ordered_pubkeys;
1180 bool have_solving_data;
1182 if (data.exists(
"scriptPubKey") && data.exists(
"desc")) {
1184 }
else if (data.exists(
"scriptPubKey")) {
1185 warnings =
ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
1186 }
else if (data.exists(
"desc")) {
1187 warnings =
ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
1198 for (
const CScript& script : script_pub_keys) {
1209 if (!
wallet.ImportPrivKeys(privkey_map, timestamp)) {
1212 if (!
wallet.ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.
key_origins, add_keypool,
internal, timestamp)) {
1215 if (!
wallet.ImportScriptPubKeys(label, script_pub_keys, have_solving_data, !
internal, timestamp)) {
1222 result.
pushKV(
"error", e);
1228 if (warnings.
size()) result.
pushKV(
"warnings", warnings);
1234 if (data.
exists(
"timestamp")) {
1235 const UniValue& timestamp = data[
"timestamp"];
1236 if (timestamp.
isNum()) {
1237 return timestamp.
getInt<int64_t>();
1238 }
else if (timestamp.
isStr() && timestamp.
get_str() ==
"now") {
1249 "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n"
1250 "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n"
1251 "Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n"
1252 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
1253 "may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n"
1254 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
1255 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
1256 "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
1267 "or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
1268 "key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
1269 "\"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
1270 "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
1271 "creation time of all keys being imported by the importmulti call will be scanned.",
1276 {
"pubkeys",
RPCArg::Type::ARR,
RPCArg::Default{
UniValue::VARR},
"Array of strings giving pubkeys to import. They must occur in P2PKH or P2WPKH scripts. They are not required when the private key is also provided (see the \"keys\" argument).",
1290 {
"keypool",
RPCArg::Type::BOOL,
RPCArg::Default{
false},
"Stating whether imported public keys should be added to the keypool for when users request new addresses. Only allowed when wallet private keys are disabled"},
1302 RPCResult::Type::ARR,
"",
"Response is an array with the same size as the input that has the execution result",
1319 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
1320 "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1321 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'")
1331 wallet.BlockUntilSyncedToCurrentChain();
1335 const UniValue& requests = mainRequest.params[0];
1338 bool fRescan =
true;
1340 if (!mainRequest.params[1].isNull()) {
1341 const UniValue& options = mainRequest.params[1];
1343 if (options.
exists(
"rescan")) {
1344 fRescan = options[
"rescan"].
get_bool();
1349 if (fRescan && !reserver.
reserve()) {
1354 bool fRunScan =
false;
1355 int64_t nLowestTimestamp = 0;
1358 LOCK(pwallet->cs_wallet);
1361 bool is_watchonly{
true};
1362 for (
size_t i = 0; i < requests.
size(); ++i) {
1363 const UniValue& request = requests[i];
1364 if (!request.
exists(
"watchonly") || !request[
"watchonly"].
get_bool()) {
1365 is_watchonly =
false;
1373 CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(),
FoundBlock().time(nLowestTimestamp).mtpTime(now)));
1378 const int64_t minimumTimestamp = 1;
1390 if (result[
"success"].get_bool()) {
1395 if (timestamp < nLowestTimestamp) {
1396 nLowestTimestamp = timestamp;
1400 if (fRescan && fRunScan && requests.
size()) {
1401 int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver,
true);
1402 pwallet->ResubmitWalletTransactions(
false,
true);
1404 if (pwallet->IsAbortingRescan()) {
1407 if (scannedTime > nLowestTimestamp) {
1408 std::vector<UniValue> results = response.
getValues();
1417 if (scannedTime <=
GetImportTimestamp(request, now) || results.at(i).exists(
"error")) {
1426 strprintf(
"Rescan failed for key with creation timestamp %d. There was an error reading a "
1427 "block from time %d, which is after or within %d seconds of key creation, and "
1428 "could contain transactions pertaining to the key. As a result, transactions "
1429 "and coins using this key may not appear in the wallet. This error could be "
1430 "caused by pruning or data corruption (see bitcoind log for details) and could "
1431 "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1432 "option and rescanblockchain RPC).",
1452 if (!data.exists(
"desc")) {
1456 const std::string& descriptor = data[
"desc"].get_str();
1457 const bool active = data.exists(
"active") ? data[
"active"].get_bool() :
false;
1458 const bool internal = data.exists(
"internal") ? data[
"internal"].get_bool() :
false;
1464 auto parsed_desc =
Parse(descriptor, keys,
error,
true);
1470 int64_t range_start = 0, range_end = 1, next_index = 0;
1471 if (!parsed_desc->IsRange() && data.exists(
"range")) {
1473 }
else if (parsed_desc->IsRange()) {
1474 if (data.exists(
"range")) {
1476 range_start = range.first;
1477 range_end = range.second + 1;
1479 warnings.
push_back(
"Range not given, using default keypool range");
1483 next_index = range_start;
1485 if (data.exists(
"next_index")) {
1486 next_index = data[
"next_index"].getInt<int64_t>();
1488 if (next_index < range_start || next_index >= range_end) {
1495 if (active && !parsed_desc->IsRange()) {
1500 if (data.exists(
"range") && data.exists(
"label")) {
1505 if (
internal && data.exists(
"label")) {
1510 if (active && !parsed_desc->IsSingleType()) {
1521 std::vector<CScript> scripts;
1522 if (!parsed_desc->Expand(0, keys, scripts, expand_keys)) {
1523 throw JSONRPCError(
RPC_WALLET_ERROR,
"Cannot expand descriptor. Probably because of hardened derivations without private keys provided");
1525 parsed_desc->ExpandPrivate(0, keys, expand_keys);
1528 bool have_all_privkeys = !expand_keys.
keys.empty();
1529 for (
const auto& entry : expand_keys.
origins) {
1530 const CKeyID& key_id = entry.first;
1532 if (!expand_keys.
GetKey(key_id, key)) {
1533 have_all_privkeys =
false;
1540 if (keys.
keys.empty()) {
1543 if (!have_all_privkeys) {
1544 warnings.
push_back(
"Not all private keys provided. Some wallet functionality may return unexpected errors");
1548 WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
1551 auto existing_spk_manager =
wallet.GetDescriptorScriptPubKeyMan(w_desc);
1552 if (existing_spk_manager) {
1553 if (!existing_spk_manager->CanUpdateToWalletDescriptor(w_desc,
error)) {
1559 auto spk_manager =
wallet.AddWalletDescriptor(w_desc, keys, label,
internal);
1560 if (spk_manager ==
nullptr) {
1567 warnings.
push_back(
"Unknown output type, cannot set descriptor to active.");
1569 wallet.AddActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.
descriptor->GetOutputType(),
internal);
1573 wallet.DeactivateScriptPubKeyMan(spk_manager->GetID(), *w_desc.
descriptor->GetOutputType(),
internal);
1580 result.
pushKV(
"error", e);
1582 if (warnings.
size()) result.
pushKV(
"warnings", warnings);
1589 "\nImport descriptors. This will trigger a rescan of the blockchain based on the earliest timestamp of all descriptors being imported. Requires a new wallet backup.\n"
1590 "\nNote: This call can take over an hour to complete if using an early timestamp; during that time, other rpc calls\n"
1591 "may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n"
1592 "The rescan is significantly faster if block filters are available (using startup option \"-blockfilterindex=1\").\n",
1603 "Use the string \"now\" to substitute the current synced blockchain time.\n"
1604 "\"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n"
1605 "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n"
1606 "of all descriptors being imported will be scanned as well as the mempool.",
1617 RPCResult::Type::ARR,
"",
"Response is an array with the same size as the input that has the execution result",
1634 HelpExampleCli(
"importdescriptors",
"'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"internal\": true }, "
1635 "{ \"desc\": \"<my descriptor 2>\", \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1636 HelpExampleCli(
"importdescriptors",
"'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"active\": true, \"range\": [0,100], \"label\": \"<my bech32 wallet>\" }]'")
1646 wallet.BlockUntilSyncedToCurrentChain();
1658 const UniValue& requests = main_request.params[0];
1659 const int64_t minimum_timestamp = 1;
1661 int64_t lowest_timestamp = 0;
1662 bool rescan =
false;
1665 LOCK(pwallet->cs_wallet);
1668 CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(),
FoundBlock().time(lowest_timestamp).mtpTime(now)));
1673 const int64_t timestamp = std::max(
GetImportTimestamp(request, now), minimum_timestamp);
1677 if (lowest_timestamp > timestamp ) {
1678 lowest_timestamp = timestamp;
1682 if (!rescan && result[
"success"].get_bool()) {
1686 pwallet->ConnectScriptPubKeyManNotifiers();
1691 int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver,
true);
1692 pwallet->ResubmitWalletTransactions(
false,
true);
1694 if (pwallet->IsAbortingRescan()) {
1698 if (scanned_time > lowest_timestamp) {
1699 std::vector<UniValue> results = response.
getValues();
1704 for (
unsigned int i = 0; i < requests.
size(); ++i) {
1711 if (scanned_time <=
GetImportTimestamp(request, now) || results.at(i).exists(
"error")) {
1720 strprintf(
"Rescan failed for descriptor with timestamp %d. There was an error reading a "
1721 "block from time %d, which is after or within %d seconds of key creation, and "
1722 "could contain transactions pertaining to the desc. As a result, transactions "
1723 "and coins using this desc may not appear in the wallet. This error could be "
1724 "caused by pruning or data corruption (see bitcoind log for details) and could "
1725 "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1726 "option and rescanblockchain RPC).",
1743 "\nList descriptors imported into a descriptor-enabled wallet.\n",
1749 {
RPCResult::Type::ARR,
"descriptors",
"Array of descriptor objects (sorted by descriptor string representation)",
1754 {
RPCResult::Type::BOOL,
"active",
"Whether this descriptor is currently used to generate new addresses"},
1755 {
RPCResult::Type::BOOL,
"internal",
true,
"True if this descriptor is used to generate change addresses. False if this descriptor is used to generate receiving addresses; defined only for active descriptors"},
1760 {
RPCResult::Type::NUM,
"next",
true,
"The next index to generate addresses from; defined only for ranged descriptors"},
1777 const bool priv = !request.params[0].isNull() && request.params[0].get_bool();
1784 const auto active_spk_mans =
wallet->GetActiveScriptPubKeyMans();
1786 struct WalletDescInfo {
1787 std::string descriptor;
1788 uint64_t creation_time;
1790 std::optional<bool>
internal;
1791 std::optional<std::pair<int64_t,int64_t>> range;
1795 std::vector<WalletDescInfo> wallet_descriptors;
1796 for (
const auto& spk_man :
wallet->GetAllScriptPubKeyMans()) {
1798 if (!desc_spk_man) {
1801 LOCK(desc_spk_man->cs_desc_man);
1802 const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
1803 std::string descriptor;
1804 if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
1807 const bool is_range = wallet_descriptor.descriptor->IsRange();
1808 wallet_descriptors.push_back({
1810 wallet_descriptor.creation_time,
1811 active_spk_mans.count(desc_spk_man) != 0,
1812 wallet->IsInternalScriptPubKeyMan(desc_spk_man),
1813 is_range ? std::optional(std::make_pair(wallet_descriptor.range_start, wallet_descriptor.range_end)) : std::nullopt,
1814 wallet_descriptor.next_index
1818 std::sort(wallet_descriptors.begin(), wallet_descriptors.end(), [](
const auto& a,
const auto& b) {
1819 return a.descriptor < b.descriptor;
1823 for (
const WalletDescInfo& info : wallet_descriptors) {
1825 spk.
pushKV(
"desc", info.descriptor);
1826 spk.
pushKV(
"timestamp", info.creation_time);
1827 spk.
pushKV(
"active", info.active);
1828 if (info.internal.has_value()) {
1829 spk.
pushKV(
"internal", info.internal.value());
1831 if (info.range.has_value()) {
1834 range.
push_back(info.range->second - 1);
1835 spk.
pushKV(
"range", range);
1836 spk.
pushKV(
"next", info.next_index);
1843 response.
pushKV(
"descriptors", descriptors);
1853 "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n",
1869 pwallet->BlockUntilSyncedToCurrentChain();
1871 LOCK(pwallet->cs_wallet);
1873 std::string strDest = request.params[0].get_str();
1874 if (!pwallet->BackupWallet(strDest)) {
1888 "\nRestore and loads a wallet from backup.\n"
1889 "\nThe rescan is significantly faster if a descriptor wallet is restored"
1890 "\nand block filters are available (using startup option \"-blockfilterindex=1\").\n",
1904 HelpExampleCli(
"restorewallet",
"\"testwallet\" \"home\\backups\\backup-file.bak\"")
1905 +
HelpExampleRpc(
"restorewallet",
"\"testwallet\" \"home\\backups\\backup-file.bak\"")
1906 +
HelpExampleCliNamed(
"restorewallet", {{
"wallet_name",
"testwallet"}, {
"backup_file",
"home\\backups\\backup-file.bak\""}, {
"load_on_startup",
true}})
1907 +
HelpExampleRpcNamed(
"restorewallet", {{
"wallet_name",
"testwallet"}, {
"backup_file",
"home\\backups\\backup-file.bak\""}, {
"load_on_startup",
true}})
1914 auto backup_file =
fs::u8path(request.params[1].get_str());
1916 std::string wallet_name = request.params[0].get_str();
1918 std::optional<bool> load_on_start = request.params[2].isNull() ? std::nullopt : std::optional<bool>(request.params[2].get_bool());
1922 std::vector<bilingual_str> warnings;
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.
#define NONFATAL_UNREACHABLE()
NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
An encapsulated private key.
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 relay blocks as header + vector<merkle branch> to filtered nodes.
CBlockHeader header
Public only for unit testing.
uint256 ExtractMatches(std::vector< uint256 > &vMatch, std::vector< unsigned int > &vnIndex)
extract the matching txid's represented by this partial merkle tree and their respective indices with...
An encapsulated public key.
bool IsCompressed() const
Check whether this is a compressed 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)
Double ended buffer combining vector and stream-like interfaces.
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
virtual std::set< CScriptID > GetCScripts() const
RecursiveMutex cs_KeyStore
void push_back(UniValue val)
const std::string & get_str() const
enum VType getType() const
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
bool exists(const std::string &key) const
void pushKV(std::string key, UniValue val)
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
std::string u8string() const
Helper for findBlock to selectively return pieces of block data.
iterator insert(iterator pos, const T &value)
CKeyID seed_id
seed hash160
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool GetKey(const CKeyID &address, CKey &keyOut) const override
const CHDChain & GetHDChain() const
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
Descriptor with some wallet metadata.
std::shared_ptr< Descriptor > descriptor
RAII object to check and reserve a wallet rescan.
std::string FormatFullVersion()
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
@ WITNESS_V0
Witness v0 (P2WPKH and P2WSH); see BIP 141.
std::string EncodeExtKey(const CExtKey &key)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
CKey DecodeSecret(const std::string &str)
static path absolute(const path &p)
static path u8path(const std::string &utf8_str)
static bool exists(const path &p)
static UniValue ProcessDescriptorImport(CWallet &wallet, const UniValue &data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
static std::string RecurseImportData(const CScript &script, ImportData &import_data, const ScriptContext script_ctx)
RPCHelpMan removeprunedfunds()
RPCHelpMan importwallet()
static void RescanWallet(CWallet &wallet, const WalletRescanReserver &reserver, int64_t time_begin=TIMESTAMP_MIN, bool update=true)
static std::string DecodeDumpString(const std::string &str)
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
void EnsureWalletIsUnlocked(const CWallet &wallet)
const LegacyScriptPubKeyMan & EnsureConstLegacyScriptPubKeyMan(const CWallet &wallet)
RPCHelpMan backupwallet()
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)
RPCHelpMan importaddress()
RPCHelpMan importprunedfunds()
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
RPCHelpMan importprivkey()
WalletContext & EnsureWalletContext(const std::any &context)
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
RPCHelpMan listdescriptors()
RPCHelpMan importpubkey()
static const int64_t TIMESTAMP_MIN
std::string LabelFromValue(const UniValue &value)
RPCHelpMan restorewallet()
static void EnsureBlockDataFromTime(const CWallet &wallet, int64_t timestamp)
std::shared_ptr< CWallet > RestoreWallet(WalletContext &context, const fs::path &backup_file, const std::string &wallet_name, std::optional< bool > load_on_start, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
RPCHelpMan importdescriptors()
int64_t ParseISO8601DateTime(const std::string &str)
static int64_t GetImportTimestamp(const UniValue &data, int64_t now)
static bool GetWalletAddressesForKey(const LegacyScriptPubKeyMan *spk_man, const CWallet &wallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
static std::string EncodeDumpString(const std::string &str)
static UniValue ProcessImport(CWallet &wallet, const UniValue &data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
static UniValue ProcessImportLegacy(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)
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.
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
UniValue JSONRPCError(int code, const std::string &message)
@ RPC_MISC_ERROR
General application defined errors.
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_WALLET_ERROR
Wallet errors.
@ 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< unsigned char > ParseHexV(const UniValue &v, std::string strName)
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)
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
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.
@ WITNESS_UNKNOWN
Only for Witness versions not already defined above.
@ NULL_DATA
unspendable OP_RETURN script that carries data
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::vector< std::string > SplitString(std::string_view str, char sep)
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
void SetSeed(Span< const std::byte > seed)
A mutable version of CTransaction.
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
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::vector< uint32_t > path
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ STR_HEX
Special type that is a STR with only hex chars.
std::string DefaultHint
Hint for default value.
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
std::vector< std::string > type_str
Should be empty unless it is supposed to override the auto-generated type strings....
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
@ ELISION
Special type to denote elision (...)
@ ARR_FIXED
Special array that has a fixed number of entries.
std::unique_ptr< CScript > redeemscript
Provided redeemScript; will be moved to import_scripts if relevant.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > key_origins
std::unique_ptr< CScript > witnessscript
Provided witnessScript; 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
State of transaction confirmed in a block.
WalletContext struct containing references to state shared between CWallet instances,...
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool error(const char *fmt, const Args &... args)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
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)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< Byte > ParseHex(std::string_view str)
Parse the hex string into bytes (uint8_t or std::byte).
bool IsHex(std::string_view str)