Skip to content

Commit 4cac0dd

Browse files
jnewberymeshcollider
authored andcommitted
[wallet] Add ProcessImportLegacy()
This commit adds a ProcessImportLegacy() function which currently does nothing. It also unindents a block of code for a future move-only change. Reviewer hint: review with -w to ignore whitespace changes.
1 parent a1b25e1 commit 4cac0dd

File tree

1 file changed

+124
-116
lines changed

1 file changed

+124
-116
lines changed

src/wallet/rpcdump.cpp

Lines changed: 124 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,12 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
964964
}
965965
}
966966

967+
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)
968+
{
969+
UniValue warnings(UniValue::VARR);
970+
return warnings;
971+
}
972+
967973
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
968974
{
969975
UniValue warnings(UniValue::VARR);
@@ -983,141 +989,143 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
983989
std::set<CScript> script_pub_keys;
984990
bool have_solving_data;
985991

986-
// First ensure scriptPubKey has either a script or JSON with "address" string
987-
const UniValue& scriptPubKey = data["scriptPubKey"];
988-
bool isScript = scriptPubKey.getType() == UniValue::VSTR;
989-
if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) {
990-
throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string");
992+
warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data);
993+
994+
// First ensure scriptPubKey has either a script or JSON with "address" string
995+
const UniValue& scriptPubKey = data["scriptPubKey"];
996+
bool isScript = scriptPubKey.getType() == UniValue::VSTR;
997+
if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) {
998+
throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string");
999+
}
1000+
const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
1001+
1002+
// Optional fields.
1003+
const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
1004+
const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : "";
1005+
const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
1006+
const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
1007+
const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
1008+
1009+
// If private keys are disabled, abort if private keys are being imported
1010+
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) {
1011+
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
1012+
}
1013+
1014+
// Generate the script and destination for the scriptPubKey provided
1015+
CScript script;
1016+
CTxDestination dest;
1017+
if (!isScript) {
1018+
dest = DecodeDestination(output);
1019+
if (!IsValidDestination(dest)) {
1020+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\"");
9911021
}
992-
const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
993-
994-
// Optional fields.
995-
const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
996-
const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : "";
997-
const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
998-
const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
999-
const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
1000-
1001-
// If private keys are disabled, abort if private keys are being imported
1002-
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) {
1003-
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
1022+
script = GetScriptForDestination(dest);
1023+
} else {
1024+
if (!IsHex(output)) {
1025+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\"");
10041026
}
1005-
1006-
// Generate the script and destination for the scriptPubKey provided
1007-
CScript script;
1008-
CTxDestination dest;
1009-
if (!isScript) {
1010-
dest = DecodeDestination(output);
1011-
if (!IsValidDestination(dest)) {
1012-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\"");
1013-
}
1014-
script = GetScriptForDestination(dest);
1015-
} else {
1016-
if (!IsHex(output)) {
1017-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\"");
1018-
}
1019-
std::vector<unsigned char> vData(ParseHex(output));
1020-
script = CScript(vData.begin(), vData.end());
1021-
if (!ExtractDestination(script, dest) && !internal) {
1022-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
1023-
}
1027+
std::vector<unsigned char> vData(ParseHex(output));
1028+
script = CScript(vData.begin(), vData.end());
1029+
if (!ExtractDestination(script, dest) && !internal) {
1030+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
10241031
}
1025-
script_pub_keys.emplace(script);
1032+
}
1033+
script_pub_keys.emplace(script);
10261034

1027-
// Parse all arguments
1028-
if (strRedeemScript.size()) {
1029-
if (!IsHex(strRedeemScript)) {
1030-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string");
1031-
}
1032-
auto parsed_redeemscript = ParseHex(strRedeemScript);
1033-
import_data.redeemscript = MakeUnique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end());
1035+
// Parse all arguments
1036+
if (strRedeemScript.size()) {
1037+
if (!IsHex(strRedeemScript)) {
1038+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string");
10341039
}
1035-
if (witness_script_hex.size()) {
1036-
if (!IsHex(witness_script_hex)) {
1037-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script \"" + witness_script_hex + "\": must be hex string");
1038-
}
1039-
auto parsed_witnessscript = ParseHex(witness_script_hex);
1040-
import_data.witnessscript = MakeUnique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
1040+
auto parsed_redeemscript = ParseHex(strRedeemScript);
1041+
import_data.redeemscript = MakeUnique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end());
1042+
}
1043+
if (witness_script_hex.size()) {
1044+
if (!IsHex(witness_script_hex)) {
1045+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script \"" + witness_script_hex + "\": must be hex string");
10411046
}
1042-
for (size_t i = 0; i < pubKeys.size(); ++i) {
1043-
const auto& str = pubKeys[i].get_str();
1044-
if (!IsHex(str)) {
1045-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string");
1046-
}
1047-
auto parsed_pubkey = ParseHex(str);
1048-
CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end());
1049-
if (!pubkey.IsFullyValid()) {
1050-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key");
1051-
}
1052-
pubkey_map.emplace(pubkey.GetID(), pubkey);
1047+
auto parsed_witnessscript = ParseHex(witness_script_hex);
1048+
import_data.witnessscript = MakeUnique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
1049+
}
1050+
for (size_t i = 0; i < pubKeys.size(); ++i) {
1051+
const auto& str = pubKeys[i].get_str();
1052+
if (!IsHex(str)) {
1053+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string");
10531054
}
1054-
for (size_t i = 0; i < keys.size(); ++i) {
1055-
const auto& str = keys[i].get_str();
1056-
CKey key = DecodeSecret(str);
1057-
if (!key.IsValid()) {
1058-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1059-
}
1060-
CPubKey pubkey = key.GetPubKey();
1061-
CKeyID id = pubkey.GetID();
1062-
if (pubkey_map.count(id)) {
1063-
pubkey_map.erase(id);
1064-
}
1065-
privkey_map.emplace(id, key);
1055+
auto parsed_pubkey = ParseHex(str);
1056+
CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end());
1057+
if (!pubkey.IsFullyValid()) {
1058+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key");
10661059
}
1060+
pubkey_map.emplace(pubkey.GetID(), pubkey);
1061+
}
1062+
for (size_t i = 0; i < keys.size(); ++i) {
1063+
const auto& str = keys[i].get_str();
1064+
CKey key = DecodeSecret(str);
1065+
if (!key.IsValid()) {
1066+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1067+
}
1068+
CPubKey pubkey = key.GetPubKey();
1069+
CKeyID id = pubkey.GetID();
1070+
if (pubkey_map.count(id)) {
1071+
pubkey_map.erase(id);
1072+
}
1073+
privkey_map.emplace(id, key);
1074+
}
10671075

10681076

1069-
// Verify and process input data
1070-
have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size();
1071-
if (have_solving_data) {
1072-
// Match up data in import_data with the scriptPubKey in script.
1073-
auto error = RecurseImportData(script, import_data, ScriptContext::TOP);
1077+
// Verify and process input data
1078+
have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size();
1079+
if (have_solving_data) {
1080+
// Match up data in import_data with the scriptPubKey in script.
1081+
auto error = RecurseImportData(script, import_data, ScriptContext::TOP);
10741082

1075-
// Verify whether the watchonly option corresponds to the availability of private keys.
1076-
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; });
1077-
if (!watchOnly && !spendable) {
1078-
warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1079-
}
1080-
if (watchOnly && spendable) {
1081-
warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1082-
}
1083+
// Verify whether the watchonly option corresponds to the availability of private keys.
1084+
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; });
1085+
if (!watchOnly && !spendable) {
1086+
warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
1087+
}
1088+
if (watchOnly && spendable) {
1089+
warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
1090+
}
10831091

1084-
// Check that all required keys for solvability are provided.
1085-
if (error.empty()) {
1086-
for (const auto& require_key : import_data.used_keys) {
1087-
if (!require_key.second) continue; // Not a required key
1088-
if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) {
1089-
error = "some required keys are missing";
1090-
}
1092+
// Check that all required keys for solvability are provided.
1093+
if (error.empty()) {
1094+
for (const auto& require_key : import_data.used_keys) {
1095+
if (!require_key.second) continue; // Not a required key
1096+
if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) {
1097+
error = "some required keys are missing";
10911098
}
10921099
}
1100+
}
10931101

1094-
if (!error.empty()) {
1095-
warnings.push_back("Importing as non-solvable: " + error + ". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.");
1096-
import_data = ImportData();
1097-
pubkey_map.clear();
1098-
privkey_map.clear();
1099-
have_solving_data = false;
1100-
} else {
1101-
// RecurseImportData() removes any relevant redeemscript/witnessscript from import_data, so we can use that to discover if a superfluous one was provided.
1102-
if (import_data.redeemscript) warnings.push_back("Ignoring redeemscript as this is not a P2SH script.");
1103-
if (import_data.witnessscript) warnings.push_back("Ignoring witnessscript as this is not a (P2SH-)P2WSH script.");
1104-
for (auto it = privkey_map.begin(); it != privkey_map.end(); ) {
1105-
auto oldit = it++;
1106-
if (import_data.used_keys.count(oldit->first) == 0) {
1107-
warnings.push_back("Ignoring irrelevant private key.");
1108-
privkey_map.erase(oldit);
1109-
}
1102+
if (!error.empty()) {
1103+
warnings.push_back("Importing as non-solvable: " + error + ". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.");
1104+
import_data = ImportData();
1105+
pubkey_map.clear();
1106+
privkey_map.clear();
1107+
have_solving_data = false;
1108+
} else {
1109+
// RecurseImportData() removes any relevant redeemscript/witnessscript from import_data, so we can use that to discover if a superfluous one was provided.
1110+
if (import_data.redeemscript) warnings.push_back("Ignoring redeemscript as this is not a P2SH script.");
1111+
if (import_data.witnessscript) warnings.push_back("Ignoring witnessscript as this is not a (P2SH-)P2WSH script.");
1112+
for (auto it = privkey_map.begin(); it != privkey_map.end(); ) {
1113+
auto oldit = it++;
1114+
if (import_data.used_keys.count(oldit->first) == 0) {
1115+
warnings.push_back("Ignoring irrelevant private key.");
1116+
privkey_map.erase(oldit);
11101117
}
1111-
for (auto it = pubkey_map.begin(); it != pubkey_map.end(); ) {
1112-
auto oldit = it++;
1113-
auto key_data_it = import_data.used_keys.find(oldit->first);
1114-
if (key_data_it == import_data.used_keys.end() || !key_data_it->second) {
1115-
warnings.push_back("Ignoring public key \"" + HexStr(oldit->first) + "\" as it doesn't appear inside P2PKH or P2WPKH.");
1116-
pubkey_map.erase(oldit);
1117-
}
1118+
}
1119+
for (auto it = pubkey_map.begin(); it != pubkey_map.end(); ) {
1120+
auto oldit = it++;
1121+
auto key_data_it = import_data.used_keys.find(oldit->first);
1122+
if (key_data_it == import_data.used_keys.end() || !key_data_it->second) {
1123+
warnings.push_back("Ignoring public key \"" + HexStr(oldit->first) + "\" as it doesn't appear inside P2PKH or P2WPKH.");
1124+
pubkey_map.erase(oldit);
11181125
}
11191126
}
11201127
}
1128+
}
11211129

11221130
// Check whether we have any work to do
11231131
for (const CScript& script : script_pub_keys) {

0 commit comments

Comments
 (0)