5#include <bitcoin-build-config.h>
41 std::stringstream
ret;
42 for (
const unsigned char c : str) {
43 if (c <= 32 || c >= 128 || c ==
'%') {
53 std::stringstream
ret;
54 for (
unsigned int pos = 0; pos < str.length(); pos++) {
55 unsigned char c = str[pos];
56 if (c ==
'%' && pos+2 < str.length()) {
57 c = (((str[pos+1]>>6)*9+((str[pos+1]-
'0')&15)) << 4) |
58 ((str[pos+2]>>6)*9+((str[pos+2]-
'0')&15));
68 bool fLabelFound =
false;
70 spk_man->GetKey(keyid, key);
72 const auto* address_book_entry =
wallet.FindAddressBookEntry(dest);
73 if (address_book_entry) {
74 if (!strAddr.empty()) {
92 int64_t scanned_time =
wallet.RescanFromTime(time_begin, reserver, update);
93 if (
wallet.IsAbortingRescan()) {
95 }
else if (scanned_time > time_begin) {
102 auto& chain{
wallet.chain()};
103 if (!chain.havePruned()) {
111 if (found && !chain.hasBlocks(tip_hash, height)) {
119 "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
120 "Hint: use importmulti to import more than one private key.\n"
121 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
122 "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"
123 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
124 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
125 "Note: Use \"getwalletinfo\" to query the scanning progress.\n"
126 "Note: This command is only compatible with legacy wallets. Use \"importdescriptors\" with \"combo(X)\" for descriptor wallets.\n",
134 "\nDump a private key\n"
136 "\nImport the private key with rescan\n"
138 "\nImport using a label and without rescan\n"
139 +
HelpExampleCli(
"importprivkey",
"\"mykey\" \"testing\" false") +
140 "\nImport using default blank label and without rescan\n"
142 "\nAs a JSON-RPC call\n"
143 +
HelpExampleRpc(
"importprivkey",
"\"mykey\", \"testing\", false")
159 LOCK(pwallet->cs_wallet);
163 std::string strSecret = request.params[0].get_str();
167 if (!request.params[2].isNull())
168 fRescan = request.params[2].get_bool();
170 if (fRescan && pwallet->chain().havePruned()) {
177 if (fRescan && !reserver.
reserve()) {
188 pwallet->MarkDirty();
194 if (!request.params[1].isNull() || !pwallet->FindAddressBookEntry(dest)) {
200 if (!pwallet->ImportPrivKeys({{vchAddress, key}}, 1)) {
222 "\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"
223 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
224 "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"
225 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
226 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
227 "If you have the full public key, you should call importpubkey instead of this.\n"
228 "Hint: use importmulti to import more than one address.\n"
229 "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
230 "as change, and not show up in many RPCs.\n"
231 "Note: Use \"getwalletinfo\" to query the scanning progress.\n"
232 "Note: This command is only compatible with legacy wallets. Use \"importdescriptors\" for descriptor wallets.\n",
241 "\nImport an address with rescan\n"
243 "\nImport using a label without rescan\n"
244 +
HelpExampleCli(
"importaddress",
"\"myaddress\" \"testing\" false") +
245 "\nAs a JSON-RPC call\n"
246 +
HelpExampleRpc(
"importaddress",
"\"myaddress\", \"testing\", false")
259 if (!request.params[2].isNull())
260 fRescan = request.params[2].get_bool();
262 if (fRescan && pwallet->chain().havePruned()) {
270 if (fRescan && !reserver.
reserve()) {
276 if (!request.params[3].isNull())
277 fP2SH = request.params[3].get_bool();
280 LOCK(pwallet->cs_wallet);
291 pwallet->MarkDirty();
294 }
else if (
IsHex(request.params[0].get_str())) {
295 std::vector<unsigned char>
data(
ParseHex(request.params[0].get_str()));
298 std::set<CScript> scripts = {redeem_script};
299 pwallet->ImportScripts(scripts, 0);
305 pwallet->ImportScriptPubKeys(strLabel, scripts,
false,
true, 1);
313 pwallet->ResubmitWalletTransactions(
false,
true);
324 "\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",
337 if (!
DecodeHexTx(tx, request.params[0].get_str())) {
347 std::vector<uint256> vMatch;
348 std::vector<unsigned int> vIndex;
353 LOCK(pwallet->cs_wallet);
355 if (!pwallet->chain().findAncestorByHash(pwallet->GetLastBlockHash(), merkleBlock.
header.
GetHash(),
FoundBlock().height(height))) {
359 std::vector<uint256>::const_iterator it;
360 if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx)) == vMatch.end()) {
364 unsigned int txnIndex = vIndex[it - vMatch.begin()];
367 if (pwallet->IsMine(*tx_ref)) {
380 "\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",
386 HelpExampleCli(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
387 "\nAs a JSON-RPC call\n"
388 +
HelpExampleRpc(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
395 LOCK(pwallet->cs_wallet);
398 std::vector<uint256> vHash;
399 vHash.push_back(hash);
400 if (
auto res = pwallet->RemoveTxs(vHash); !res) {
412 "\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"
413 "Hint: use importmulti to import more than one public key.\n"
414 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
415 "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"
416 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
417 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
418 "Note: Use \"getwalletinfo\" to query the scanning progress.\n"
419 "Note: This command is only compatible with legacy wallets. Use \"importdescriptors\" with \"combo(X)\" for descriptor wallets.\n",
427 "\nImport a public key with rescan\n"
429 "\nImport using a label without rescan\n"
430 +
HelpExampleCli(
"importpubkey",
"\"mypubkey\" \"testing\" false") +
431 "\nAs a JSON-RPC call\n"
432 +
HelpExampleRpc(
"importpubkey",
"\"mypubkey\", \"testing\", false")
445 if (!request.params[2].isNull())
446 fRescan = request.params[2].get_bool();
448 if (fRescan && pwallet->chain().havePruned()) {
456 if (fRescan && !reserver.
reserve()) {
463 LOCK(pwallet->cs_wallet);
465 std::set<CScript> script_pub_keys;
470 pwallet->MarkDirty();
472 pwallet->ImportScriptPubKeys(strLabel, script_pub_keys,
true,
true, 1);
474 pwallet->ImportPubKeys({{pubKey.
GetID(),
false}}, {{pubKey.
GetID(), pubKey}} , {},
false, 1);
479 pwallet->ResubmitWalletTransactions(
false,
true);
491 "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
492 "Note: Blockchain and Mempool will be rescanned after a successful import. Use \"getwalletinfo\" to query the scanning progress.\n"
493 "Note: This command is only compatible with legacy wallets.\n",
499 "\nDump the wallet\n"
501 "\nImport the wallet\n"
503 "\nImport using the json rpc call\n"
518 int64_t nTimeBegin = 0;
521 LOCK(pwallet->cs_wallet);
526 file.open(
fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate);
527 if (!file.is_open()) {
532 int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
533 file.seekg(0, file.beg);
537 pwallet->chain().showProgress(
strprintf(
"%s %s", pwallet->GetDisplayName(),
_(
"Importing…").translated), 0,
false);
538 std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
539 std::vector<std::pair<CScript, int64_t>> scripts;
540 while (file.good()) {
541 pwallet->chain().showProgress(
"", std::max(1, std::min(50, (
int)(((
double)file.tellg() / (
double)nFilesize) * 100))),
false);
543 std::getline(file, line);
544 if (line.empty() || line[0] ==
'#')
547 std::vector<std::string> vstr =
SplitString(line,
' ');
553 std::string strLabel;
555 for (
unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
556 if (vstr[nStr].front() ==
'#')
558 if (vstr[nStr] ==
"change=1")
560 if (vstr[nStr] ==
"reserve=1")
562 if (vstr[nStr].substr(0,6) ==
"label=") {
567 nTimeBegin = std::min(nTimeBegin, nTime);
568 keys.emplace_back(key, nTime, fLabel, strLabel);
569 }
else if(
IsHex(vstr[0])) {
570 std::vector<unsigned char> vData(
ParseHex(vstr[0]));
573 if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
574 scripts.emplace_back(
script, birth_time);
581 pwallet->chain().showProgress(
"", 100,
false);
584 double total = (double)(keys.size() + scripts.size());
586 for (
const auto& key_tuple : keys) {
587 pwallet->chain().showProgress(
"", std::max(50, std::min(75, (
int)((progress / total) * 100) + 50)),
false);
588 const CKey& key = std::get<0>(key_tuple);
589 int64_t time = std::get<1>(key_tuple);
590 bool has_label = std::get<2>(key_tuple);
591 std::string label = std::get<3>(key_tuple);
599 if (!pwallet->ImportPrivKeys({{keyid, key}}, time)) {
606 pwallet->SetAddressBook(
PKHash(keyid), label, AddressPurpose::RECEIVE);
609 for (
const auto& script_pair : scripts) {
610 pwallet->chain().showProgress(
"", std::max(50, std::min(75, (
int)((progress / total) * 100) + 50)),
false);
612 int64_t time = script_pair.second;
614 if (!pwallet->ImportScripts({script}, time)) {
615 pwallet->WalletLogPrintf(
"Error importing script %s\n",
HexStr(
script));
622 pwallet->chain().showProgress(
"", 100,
false);
624 pwallet->chain().showProgress(
"", 100,
false);
626 pwallet->MarkDirty();
639 "\nReveals the private key corresponding to 'address'.\n"
640 "Then the importprivkey can be used with this output\n"
641 "Note: This command is only compatible with legacy wallets.\n",
664 std::string strAddress = request.params[0].get_str();
670 if (keyid.IsNull()) {
674 if (!spk_man.
GetKey(keyid, vchSecret)) {
686 "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
687 "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n"
688 "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"
689 "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n"
690 "Note: This command is only compatible with legacy wallets.\n",
714 wallet.BlockUntilSyncedToCurrentChain();
737 std::map<CKeyID, int64_t> mapKeyBirth;
738 wallet.GetKeyBirthTimes(mapKeyBirth);
740 int64_t block_time = 0;
748 std::set<CScriptID> scripts = spk_man.
GetCScripts();
751 std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
752 vKeyBirth.reserve(mapKeyBirth.size());
753 for (
const auto& entry : mapKeyBirth) {
754 vKeyBirth.emplace_back(entry.second, entry.first);
757 std::sort(vKeyBirth.begin(), vKeyBirth.end());
762 file <<
strprintf(
"# * Best block at time of backup was %i (%s),\n",
wallet.GetLastBlockHeight(),
wallet.GetLastBlockHash().ToString());
771 if (spk_man.
GetKey(seed_id, seed)) {
775 file <<
"# extended private masterkey: " <<
EncodeExtKey(masterKey) <<
"\n\n";
778 for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
779 const CKeyID &keyid = it->second;
782 std::string strLabel;
784 if (spk_man.
GetKey(keyid, key)) {
786 const auto it{spk_man.mapKeyMetadata.find(keyid)};
787 if (it != spk_man.mapKeyMetadata.end()) metadata = it->second;
791 }
else if (keyid == seed_id) {
793 }
else if (mapKeyPool.count(keyid)) {
796 file <<
"inactivehdseed=1";
804 for (
const CScriptID &scriptid : scripts) {
806 std::string create_time =
"0";
809 auto it = spk_man.m_script_metadata.find(scriptid);
810 if (it != spk_man.m_script_metadata.end()) {
815 file <<
strprintf(
" # addr=%s\n", address);
819 file <<
"# End of dump\n";
855 std::vector<std::vector<unsigned char>> solverdata;
858 switch (script_type) {
875 if (!subscript)
return "missing redeemscript";
876 if (
CScriptID(*subscript) !=
id)
return "redeemScript does not match the scriptPubKey";
881 for (
size_t i = 1; i + 1< solverdata.size(); ++i) {
891 if (!subscript)
return "missing witnessscript";
892 if (
CScriptID(*subscript) !=
id)
return "witnessScript does not match the scriptPubKey or redeemScript";
893 if (script_ctx == ScriptContext::TOP) {
903 if (script_ctx == ScriptContext::TOP) {
909 return "unspendable script";
914 return "unrecognized script";
919static 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<std::pair<CKeyID, bool>>& ordered_pubkeys)
929 const std::string& output = isScript ? scriptPubKey.
get_str() : scriptPubKey[
"address"].
get_str();
932 const std::string& strRedeemScript =
data.exists(
"redeemscript") ?
data[
"redeemscript"].get_str() :
"";
933 const std::string& witness_script_hex =
data.exists(
"witnessscript") ?
data[
"witnessscript"].get_str() :
"";
936 const bool internal =
data.exists(
"internal") ?
data[
"internal"].get_bool() :
false;
937 const bool watchOnly =
data.exists(
"watchonly") ?
data[
"watchonly"].get_bool() :
false;
939 if (
data.exists(
"range")) {
955 if (!
IsHex(output)) {
958 std::vector<unsigned char> vData(
ParseHex(output));
965 script_pub_keys.emplace(
script);
968 if (strRedeemScript.size()) {
969 if (!
IsHex(strRedeemScript)) {
972 auto parsed_redeemscript =
ParseHex(strRedeemScript);
973 import_data.
redeemscript = std::make_unique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end());
975 if (witness_script_hex.size()) {
976 if (!
IsHex(witness_script_hex)) {
979 auto parsed_witnessscript =
ParseHex(witness_script_hex);
980 import_data.
witnessscript = std::make_unique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
982 for (
size_t i = 0; i < pubKeys.
size(); ++i) {
984 pubkey_map.emplace(pubkey.
GetID(), pubkey);
985 ordered_pubkeys.emplace_back(pubkey.
GetID(), internal);
987 for (
size_t i = 0; i < keys.
size(); ++i) {
988 const auto& str = keys[i].
get_str();
995 if (pubkey_map.count(
id)) {
996 pubkey_map.erase(
id);
998 privkey_map.emplace(
id, key);
1004 if (have_solving_data) {
1009 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; });
1010 if (!watchOnly && !spendable) {
1011 warnings.
push_back(
"Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1013 if (watchOnly && spendable) {
1014 warnings.
push_back(
"All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1018 if (error.empty()) {
1019 for (
const auto& require_key : import_data.
used_keys) {
1020 if (!require_key.second)
continue;
1021 if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) {
1022 error =
"some required keys are missing";
1027 if (!error.empty()) {
1028 warnings.
push_back(
"Importing as non-solvable: " + error +
". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.");
1031 privkey_map.clear();
1032 have_solving_data =
false;
1035 if (import_data.
redeemscript) warnings.
push_back(
"Ignoring redeemscript as this is not a P2SH script.");
1036 if (import_data.
witnessscript) warnings.
push_back(
"Ignoring witnessscript as this is not a (P2SH-)P2WSH script.");
1037 for (
auto it = privkey_map.begin(); it != privkey_map.end(); ) {
1039 if (import_data.
used_keys.count(oldit->first) == 0) {
1040 warnings.
push_back(
"Ignoring irrelevant private key.");
1041 privkey_map.erase(oldit);
1044 for (
auto it = pubkey_map.begin(); it != pubkey_map.end(); ) {
1046 auto key_data_it = import_data.
used_keys.find(oldit->first);
1047 if (key_data_it == import_data.
used_keys.end() || !key_data_it->second) {
1048 warnings.
push_back(
"Ignoring public key \"" +
HexStr(oldit->first) +
"\" as it doesn't appear inside P2PKH or P2WPKH.");
1049 pubkey_map.erase(oldit);
1062 const std::string& descriptor =
data[
"desc"].get_str();
1065 auto parsed_descs =
Parse(descriptor, keys, error,
true);
1066 if (parsed_descs.empty()) {
1073 std::optional<bool> internal;
1074 if (
data.exists(
"internal")) {
1075 if (parsed_descs.size() > 1) {
1078 internal =
data[
"internal"].get_bool();
1081 have_solving_data = parsed_descs.at(0)->IsSolvable();
1082 const bool watch_only =
data.exists(
"watchonly") ?
data[
"watchonly"].get_bool() :
false;
1084 int64_t range_start = 0, range_end = 0;
1085 if (!parsed_descs.at(0)->IsRange() &&
data.exists(
"range")) {
1087 }
else if (parsed_descs.at(0)->IsRange()) {
1088 if (!
data.exists(
"range")) {
1096 for (
size_t j = 0; j < parsed_descs.size(); ++j) {
1097 const auto& parsed_desc = parsed_descs.at(j);
1098 bool desc_internal = internal.has_value() && internal.value();
1099 if (parsed_descs.size() == 2) {
1100 desc_internal = j == 1;
1101 }
else if (parsed_descs.size() > 2) {
1105 for (
int i = range_start; i <= range_end; ++i) {
1107 std::vector<CScript> scripts_temp;
1108 parsed_desc->Expand(i, keys, scripts_temp, out_keys);
1109 std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end()));
1110 for (
const auto& key_pair : out_keys.
pubkeys) {
1111 ordered_pubkeys.emplace_back(key_pair.first, desc_internal);
1114 for (
const auto& x : out_keys.
scripts) {
1118 parsed_desc->ExpandPrivate(i, keys, out_keys);
1120 std::copy(out_keys.
pubkeys.begin(), out_keys.
pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end()));
1121 std::copy(out_keys.
keys.begin(), out_keys.
keys.end(), std::inserter(privkey_map, privkey_map.end()));
1126 for (
size_t i = 0; i < priv_keys.
size(); ++i) {
1127 const auto& str = priv_keys[i].
get_str();
1136 if (!pubkey_map.count(
id)) {
1137 warnings.
push_back(
"Ignoring irrelevant private key.");
1139 privkey_map.emplace(
id, key);
1147 bool spendable = std::all_of(pubkey_map.begin(), pubkey_map.end(),
1148 [&](
const std::pair<CKeyID, CPubKey>& used_key) {
1149 return privkey_map.count(used_key.first) > 0;
1151 [&](
const std::pair<
CKeyID, std::pair<CPubKey, KeyOriginInfo>>& entry) {
1152 return privkey_map.count(entry.first) > 0;
1154 if (!watch_only && !spendable) {
1155 warnings.
push_back(
"Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1157 if (watch_only && spendable) {
1158 warnings.
push_back(
"All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1170 const bool internal =
data.exists(
"internal") ?
data[
"internal"].get_bool() :
false;
1172 if (internal &&
data.exists(
"label")) {
1176 const bool add_keypool =
data.exists(
"keypool") ?
data[
"keypool"].get_bool() :
false;
1184 std::map<CKeyID, CPubKey> pubkey_map;
1185 std::map<CKeyID, CKey> privkey_map;
1186 std::set<CScript> script_pub_keys;
1187 std::vector<std::pair<CKeyID, bool>> ordered_pubkeys;
1188 bool have_solving_data;
1190 if (
data.exists(
"scriptPubKey") &&
data.exists(
"desc")) {
1192 }
else if (
data.exists(
"scriptPubKey")) {
1193 warnings =
ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data,
data, ordered_pubkeys);
1194 }
else if (
data.exists(
"desc")) {
1195 warnings =
ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data,
data, ordered_pubkeys);
1217 if (!
wallet.ImportPrivKeys(privkey_map, timestamp)) {
1220 if (!
wallet.ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.
key_origins, add_keypool, timestamp)) {
1223 if (!
wallet.ImportScriptPubKeys(label, script_pub_keys, have_solving_data, !internal, timestamp)) {
1230 result.
pushKV(
"error", e);
1242 if (
data.exists(
"timestamp")) {
1244 if (timestamp.
isNum()) {
1245 return timestamp.
getInt<int64_t>();
1246 }
else if (timestamp.
isStr() && timestamp.
get_str() ==
"now") {
1257 "\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"
1258 "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"
1259 "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"
1260 "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
1261 "may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n"
1262 "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
1263 "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
1264 "Note: Use \"getwalletinfo\" to query the scanning progress.\n"
1265 "Note: This command is only compatible with legacy wallets. Use \"importdescriptors\" for descriptor wallets.\n",
1276 "or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
1277 "key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
1278 "\"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
1279 "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
1280 "creation time of all keys being imported by the importmulti call will be scanned.",
1285 {
"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).",
1299 {
"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"},
1311 RPCResult::Type::ARR,
"",
"Response is an array with the same size as the input that has the execution result",
1328 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
1329 "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1330 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'")
1340 wallet.BlockUntilSyncedToCurrentChain();
1344 const UniValue& requests = mainRequest.params[0];
1347 bool fRescan =
true;
1349 if (!mainRequest.params[1].isNull()) {
1350 const UniValue& options = mainRequest.params[1];
1352 if (options.
exists(
"rescan")) {
1353 fRescan = options[
"rescan"].
get_bool();
1358 if (fRescan && !reserver.
reserve()) {
1363 bool fRunScan =
false;
1364 int64_t nLowestTimestamp = 0;
1367 LOCK(pwallet->cs_wallet);
1370 bool is_watchonly{
true};
1371 for (
size_t i = 0; i < requests.
size(); ++i) {
1372 const UniValue& request = requests[i];
1373 if (!request.
exists(
"watchonly") || !request[
"watchonly"].
get_bool()) {
1374 is_watchonly =
false;
1382 CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(),
FoundBlock().time(nLowestTimestamp).mtpTime(now)));
1387 const int64_t minimumTimestamp = 1;
1399 if (result[
"success"].get_bool()) {
1404 if (timestamp < nLowestTimestamp) {
1405 nLowestTimestamp = timestamp;
1409 if (fRescan && fRunScan && requests.
size()) {
1410 int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver,
true);
1411 pwallet->ResubmitWalletTransactions(
false,
true);
1413 if (pwallet->IsAbortingRescan()) {
1416 if (scannedTime > nLowestTimestamp) {
1417 std::vector<UniValue> results = response.
getValues();
1426 if (scannedTime <=
GetImportTimestamp(request, now) || results.at(i).exists(
"error")) {
1435 strprintf(
"Rescan failed for key with creation timestamp %d. There was an error reading a "
1436 "block from time %d, which is after or within %d seconds of key creation, and "
1437 "could contain transactions pertaining to the key. As a result, transactions "
1438 "and coins using this key may not appear in the wallet. This error could be "
1439 "caused by pruning or data corruption (see bitcoind log for details) and could "
1440 "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1441 "option and rescanblockchain RPC).",
1461 if (!
data.exists(
"desc")) {
1465 const std::string& descriptor =
data[
"desc"].get_str();
1466 const bool active =
data.exists(
"active") ?
data[
"active"].get_bool() :
false;
1472 auto parsed_descs =
Parse(descriptor, keys, error,
true);
1473 if (parsed_descs.empty()) {
1476 std::optional<bool> internal;
1477 if (
data.exists(
"internal")) {
1478 if (parsed_descs.size() > 1) {
1481 internal =
data[
"internal"].get_bool();
1485 int64_t range_start = 0, range_end = 1, next_index = 0;
1486 if (!parsed_descs.at(0)->IsRange() &&
data.exists(
"range")) {
1488 }
else if (parsed_descs.at(0)->IsRange()) {
1489 if (
data.exists(
"range")) {
1491 range_start = range.first;
1492 range_end = range.second + 1;
1494 warnings.
push_back(
"Range not given, using default keypool range");
1496 range_end =
wallet.m_keypool_size;
1498 next_index = range_start;
1500 if (
data.exists(
"next_index")) {
1501 next_index =
data[
"next_index"].getInt<int64_t>();
1503 if (next_index < range_start || next_index >= range_end) {
1510 if (active && !parsed_descs.at(0)->IsRange()) {
1515 if (parsed_descs.size() > 1 &&
data.exists(
"label")) {
1520 if (
data.exists(
"range") &&
data.exists(
"label")) {
1525 if (internal &&
data.exists(
"label")) {
1530 if (active && !parsed_descs.at(0)->IsSingleType()) {
1539 for (
size_t j = 0; j < parsed_descs.size(); ++j) {
1540 auto parsed_desc = std::move(parsed_descs[j]);
1541 bool desc_internal = internal.has_value() && internal.value();
1542 if (parsed_descs.size() == 2) {
1543 desc_internal = j == 1;
1544 }
else if (parsed_descs.size() > 2) {
1549 std::vector<CScript> scripts;
1550 if (!parsed_desc->Expand(0, keys, scripts, expand_keys)) {
1551 throw JSONRPCError(
RPC_WALLET_ERROR,
"Cannot expand descriptor. Probably because of hardened derivations without private keys provided");
1553 parsed_desc->ExpandPrivate(0, keys, expand_keys);
1556 bool have_all_privkeys = !expand_keys.
keys.empty();
1557 for (
const auto& entry : expand_keys.
origins) {
1558 const CKeyID& key_id = entry.first;
1560 if (!expand_keys.
GetKey(key_id, key)) {
1561 have_all_privkeys =
false;
1568 if (keys.
keys.empty()) {
1571 if (!have_all_privkeys) {
1572 warnings.
push_back(
"Not all private keys provided. Some wallet functionality may return unexpected errors");
1576 WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
1579 auto existing_spk_manager =
wallet.GetDescriptorScriptPubKeyMan(w_desc);
1580 if (existing_spk_manager) {
1581 if (!existing_spk_manager->CanUpdateToWalletDescriptor(w_desc, error)) {
1587 auto spk_manager =
wallet.AddWalletDescriptor(w_desc, keys, label, desc_internal);
1588 if (spk_manager ==
nullptr) {
1595 warnings.
push_back(
"Unknown output type, cannot set descriptor to active.");
1597 wallet.AddActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.
descriptor->GetOutputType(), desc_internal);
1601 wallet.DeactivateScriptPubKeyMan(spk_manager->GetID(), *w_desc.
descriptor->GetOutputType(), desc_internal);
1609 result.
pushKV(
"error", e);
1618 "\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"
1619 "When importing descriptors with multipath key expressions, if the multipath specifier contains exactly two elements, the descriptor produced from the second elements will be imported as an internal descriptor.\n"
1620 "\nNote: This call can take over an hour to complete if using an early timestamp; during that time, other rpc calls\n"
1621 "may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n"
1622 "The rescan is significantly faster if block filters are available (using startup option \"-blockfilterindex=1\").\n",
1633 "Use the string \"now\" to substitute the current synced blockchain time.\n"
1634 "\"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n"
1635 "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n"
1636 "of all descriptors being imported will be scanned as well as the mempool.",
1647 RPCResult::Type::ARR,
"",
"Response is an array with the same size as the input that has the execution result",
1664 HelpExampleCli(
"importdescriptors",
"'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"internal\": true }, "
1665 "{ \"desc\": \"<my descriptor 2>\", \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1666 HelpExampleCli(
"importdescriptors",
"'[{ \"desc\": \"<my descriptor>\", \"timestamp\":1455191478, \"active\": true, \"range\": [0,100], \"label\": \"<my bech32 wallet>\" }]'")
1676 wallet.BlockUntilSyncedToCurrentChain();
1684 if (!reserver.
reserve(
true)) {
1690 LOCK(pwallet->m_relock_mutex);
1692 const UniValue& requests = main_request.params[0];
1693 const int64_t minimum_timestamp = 1;
1695 int64_t lowest_timestamp = 0;
1696 bool rescan =
false;
1699 LOCK(pwallet->cs_wallet);
1702 CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(),
FoundBlock().time(lowest_timestamp).mtpTime(now)));
1707 const int64_t timestamp = std::max(
GetImportTimestamp(request, now), minimum_timestamp);
1711 if (lowest_timestamp > timestamp ) {
1712 lowest_timestamp = timestamp;
1716 if (!rescan && result[
"success"].get_bool()) {
1720 pwallet->ConnectScriptPubKeyManNotifiers();
1725 int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver,
true);
1726 pwallet->ResubmitWalletTransactions(
false,
true);
1728 if (pwallet->IsAbortingRescan()) {
1732 if (scanned_time > lowest_timestamp) {
1733 std::vector<UniValue> results = response.
getValues();
1738 for (
unsigned int i = 0; i < requests.
size(); ++i) {
1745 if (scanned_time <=
GetImportTimestamp(request, now) || results.at(i).exists(
"error")) {
1754 strprintf(
"Rescan failed for descriptor with timestamp %d. There was an error reading a "
1755 "block from time %d, which is after or within %d seconds of key creation, and "
1756 "could contain transactions pertaining to the desc. As a result, transactions "
1757 "and coins using this desc may not appear in the wallet. This error could be "
1758 "caused by pruning or data corruption (see bitcoind log for details) and could "
1759 "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
1760 "option and rescanblockchain RPC).",
1777 "\nList descriptors imported into a descriptor-enabled wallet.\n",
1783 {
RPCResult::Type::ARR,
"descriptors",
"Array of descriptor objects (sorted by descriptor string representation)",
1788 {
RPCResult::Type::BOOL,
"active",
"Whether this descriptor is currently used to generate new addresses"},
1789 {
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"},
1794 {
RPCResult::Type::NUM,
"next",
true,
"Same as next_index field. Kept for compatibility reason."},
1795 {
RPCResult::Type::NUM,
"next_index",
true,
"The next index to generate addresses from; defined only for ranged descriptors"},
1812 const bool priv = !request.params[0].isNull() && request.params[0].get_bool();
1819 const auto active_spk_mans =
wallet->GetActiveScriptPubKeyMans();
1821 struct WalletDescInfo {
1822 std::string descriptor;
1823 uint64_t creation_time;
1825 std::optional<bool> internal;
1826 std::optional<std::pair<int64_t,int64_t>> range;
1830 std::vector<WalletDescInfo> wallet_descriptors;
1831 for (
const auto& spk_man :
wallet->GetAllScriptPubKeyMans()) {
1833 if (!desc_spk_man) {
1836 LOCK(desc_spk_man->cs_desc_man);
1837 const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
1838 std::string descriptor;
1839 if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
1842 const bool is_range = wallet_descriptor.descriptor->IsRange();
1843 wallet_descriptors.push_back({
1845 wallet_descriptor.creation_time,
1846 active_spk_mans.count(desc_spk_man) != 0,
1847 wallet->IsInternalScriptPubKeyMan(desc_spk_man),
1848 is_range ? std::optional(std::make_pair(wallet_descriptor.range_start, wallet_descriptor.range_end)) : std::nullopt,
1849 wallet_descriptor.next_index
1853 std::sort(wallet_descriptors.begin(), wallet_descriptors.end(), [](
const auto& a,
const auto& b) {
1854 return a.descriptor < b.descriptor;
1858 for (
const WalletDescInfo& info : wallet_descriptors) {
1860 spk.
pushKV(
"desc", info.descriptor);
1861 spk.
pushKV(
"timestamp", info.creation_time);
1862 spk.
pushKV(
"active", info.active);
1863 if (info.internal.has_value()) {
1864 spk.
pushKV(
"internal", info.internal.value());
1866 if (info.range.has_value()) {
1869 range.
push_back(info.range->second - 1);
1870 spk.
pushKV(
"range", std::move(range));
1871 spk.
pushKV(
"next", info.next_index);
1872 spk.
pushKV(
"next_index", info.next_index);
1879 response.
pushKV(
"descriptors", std::move(descriptors));
1889 "\nSafely copies the current wallet file to the specified destination, which can either be a directory or a path with a filename.\n",
1905 pwallet->BlockUntilSyncedToCurrentChain();
1907 LOCK(pwallet->cs_wallet);
1909 std::string strDest = request.params[0].get_str();
1910 if (!pwallet->BackupWallet(strDest)) {
1924 "\nRestores and loads a wallet from backup.\n"
1925 "\nThe rescan is significantly faster if a descriptor wallet is restored"
1926 "\nand block filters are available (using startup option \"-blockfilterindex=1\").\n",
1936 {
RPCResult::Type::ARR,
"warnings",
true,
"Warning messages, if any, related to restoring and loading the wallet.",
1943 HelpExampleCli(
"restorewallet",
"\"testwallet\" \"home\\backups\\backup-file.bak\"")
1944 +
HelpExampleRpc(
"restorewallet",
"\"testwallet\" \"home\\backups\\backup-file.bak\"")
1945 +
HelpExampleCliNamed(
"restorewallet", {{
"wallet_name",
"testwallet"}, {
"backup_file",
"home\\backups\\backup-file.bak\""}, {
"load_on_startup",
true}})
1946 +
HelpExampleRpcNamed(
"restorewallet", {{
"wallet_name",
"testwallet"}, {
"backup_file",
"home\\backups\\backup-file.bak\""}, {
"load_on_startup",
true}})
1953 auto backup_file =
fs::u8path(request.params[1].get_str());
1955 std::string wallet_name = request.params[0].get_str();
1957 std::optional<bool> load_on_start = request.params[2].isNull() ? std::nullopt : std::optional<bool>(request.params[2].get_bool());
1961 std::vector<bilingual_str> warnings;
1963 const std::shared_ptr<CWallet>
wallet =
RestoreWallet(context, backup_file, wallet_name, load_on_start, status, error, warnings);
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath, bool apostrophe)
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.
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)
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization.
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
bool exists(const std::string &key) const
void pushKV(std::string key, UniValue val)
constexpr bool IsNull() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
std::string utf8string() const
Return a UTF-8 representation of the path as a std::string, for compatibility with code using std::st...
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...
const CHDChain & GetHDChain() const
bool GetKey(const CKeyID &address, CKey &keyOut) const override
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.
bool reserve(bool with_passphrase=false)
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
std::string FormatFullVersion()
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
@ 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)
std::vector< std::string > SplitString(std::string_view str, char sep)
bilingual_str ErrorString(const Result< T > &result)
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()
RPCHelpMan importaddress()
RPCHelpMan importprunedfunds()
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
RPCHelpMan importprivkey()
WalletContext & EnsureWalletContext(const std::any &context)
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)
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< std::pair< CKeyID, bool > > &ordered_pubkeys)
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()
static int64_t GetImportTimestamp(const UniValue &data, int64_t now)
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< std::pair< CKeyID, bool > > &ordered_pubkeys)
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)
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
std::vector< CTxDestination > GetAllDestinationsForKey(const CPubKey &key)
Get all destinations (potentially) supported by the wallet for the given key.
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::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string_view name)
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
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.
CPubKey HexToPubKey(const std::string &hex_in)
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
uint256 ParseHashV(const UniValue &v, std::string_view name)
Utilities: convert hex-encoded Values (throws error if not hex).
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.
@ WITNESS_UNKNOWN
Only for Witness versions not already defined above.
@ ANCHOR
anyone can spend script
@ NULL_DATA
unspendable OP_RETURN script that carries data
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
void SetSeed(Span< const std::byte > seed)
A mutable version of CTransaction.
Txid 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.
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
std::optional< int64_t > ParseISO8601DateTime(std::string_view str)
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
bilingual_str _(ConstevalStringLiteral str)
Translation function.
const char * uvTypeName(UniValue::VType t)
bool IsHex(std::string_view str)