| 943 | } |
| 944 | |
| 945 | 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) |
| 946 | { |
| 947 | UniValue warnings(UniValue::VARR); |
| 948 | |
| 949 | // First ensure scriptPubKey has either a script or JSON with "address" string |
| 950 | const UniValue& scriptPubKey = data["scriptPubKey"]; |
| 951 | bool isScript = scriptPubKey.getType() == UniValue::VSTR; |
| 952 | if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { |
| 953 | throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string"); |
| 954 | } |
| 955 | const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); |
| 956 | |
| 957 | // Optional fields. |
| 958 | const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; |
| 959 | const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : ""; |
| 960 | const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); |
| 961 | const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); |
| 962 | const bool internal = data.exists("internal") ? data["internal"].get_bool() : false; |
| 963 | const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; |
| 964 | |
| 965 | if (data.exists("range")) { |
| 966 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for a non-descriptor import"); |
| 967 | } |
| 968 | |
| 969 | // Generate the script and destination for the scriptPubKey provided |
| 970 | CScript script; |
| 971 | if (!isScript) { |
| 972 | CTxDestination dest = DecodeDestination(output); |
| 973 | if (!IsValidDestination(dest)) { |
| 974 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\""); |
| 975 | } |
| 976 | if (OutputTypeFromDestination(dest) == OutputType::BECH32M) { |
| 977 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m addresses cannot be imported into legacy wallets"); |
| 978 | } |
| 979 | script = GetScriptForDestination(dest); |
| 980 | } else { |
| 981 | if (!IsHex(output)) { |
| 982 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\""); |
| 983 | } |
| 984 | std::vector<unsigned char> vData(ParseHex(output)); |
| 985 | script = CScript(vData.begin(), vData.end()); |
| 986 | CTxDestination dest; |
| 987 | if (!ExtractDestination(script, dest) && !internal) { |
| 988 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports."); |
| 989 | } |
| 990 | } |
| 991 | script_pub_keys.emplace(script); |
| 992 | |
| 993 | // Parse all arguments |
| 994 | if (strRedeemScript.size()) { |
| 995 | if (!IsHex(strRedeemScript)) { |
| 996 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string"); |
| 997 | } |
| 998 | auto parsed_redeemscript = ParseHex(strRedeemScript); |
| 999 | import_data.redeemscript = std::make_unique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end()); |
| 1000 | } |
| 1001 | if (witness_script_hex.size()) { |
| 1002 | if (!IsHex(witness_script_hex)) { |
no test coverage detected