MCPcopy Create free account
hub / github.com/ElementsProject/elements / RecurseImportData

Function RecurseImportData

src/wallet/rpc/backup.cpp:873–943  ·  view source on GitHub ↗

Analyse the provided scriptPubKey, determining which keys and which redeem scripts from the ImportData struct are needed to spend it, and mark them as used. Returns an error string, or the empty string for success.

Source from the content-addressed store, hash-verified

871// Analyse the provided scriptPubKey, determining which keys and which redeem scripts from the ImportData struct are needed to spend it, and mark them as used.
872// Returns an error string, or the empty string for success.
873static std::string RecurseImportData(const CScript& script, ImportData& import_data, const ScriptContext script_ctx)
874{
875 // Use Solver to obtain script type and parsed pubkeys or hashes:
876 std::vector<std::vector<unsigned char>> solverdata;
877 TxoutType script_type = Solver(script, solverdata);
878
879 switch (script_type) {
880 case TxoutType::PUBKEY: {
881 CPubKey pubkey(solverdata[0]);
882 import_data.used_keys.emplace(pubkey.GetID(), false);
883 return "";
884 }
885 case TxoutType::PUBKEYHASH: {
886 CKeyID id = CKeyID(uint160(solverdata[0]));
887 import_data.used_keys[id] = true;
888 return "";
889 }
890 case TxoutType::SCRIPTHASH: {
891 if (script_ctx == ScriptContext::P2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside another P2SH");
892 if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside a P2WSH");
893 CHECK_NONFATAL(script_ctx == ScriptContext::TOP);
894 CScriptID id = CScriptID(uint160(solverdata[0]));
895 auto subscript = std::move(import_data.redeemscript); // Remove redeemscript from import_data to check for superfluous script later.
896 if (!subscript) return "missing redeemscript";
897 if (CScriptID(*subscript) != id) return "redeemScript does not match the scriptPubKey";
898 import_data.import_scripts.emplace(*subscript);
899 return RecurseImportData(*subscript, import_data, ScriptContext::P2SH);
900 }
901 case TxoutType::MULTISIG: {
902 for (size_t i = 1; i + 1< solverdata.size(); ++i) {
903 CPubKey pubkey(solverdata[i]);
904 import_data.used_keys.emplace(pubkey.GetID(), false);
905 }
906 return "";
907 }
908 case TxoutType::WITNESS_V0_SCRIPTHASH: {
909 if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WSH inside another P2WSH");
910 uint256 fullid(solverdata[0]);
911 CScriptID id;
912 CRIPEMD160().Write(fullid.begin(), fullid.size()).Finalize(id.begin());
913 auto subscript = std::move(import_data.witnessscript); // Remove redeemscript from import_data to check for superfluous script later.
914 if (!subscript) return "missing witnessscript";
915 if (CScriptID(*subscript) != id) return "witnessScript does not match the scriptPubKey or redeemScript";
916 if (script_ctx == ScriptContext::TOP) {
917 import_data.import_scripts.emplace(script); // Special rule for IsMine: native P2WSH requires the TOP script imported (see script/ismine.cpp)
918 }
919 import_data.import_scripts.emplace(*subscript);
920 return RecurseImportData(*subscript, import_data, ScriptContext::WITNESS_V0);
921 }
922 case TxoutType::WITNESS_V0_KEYHASH: {
923 if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WPKH inside P2WSH");
924 CKeyID id = CKeyID(uint160(solverdata[0]));
925 import_data.used_keys[id] = true;
926 if (script_ctx == ScriptContext::TOP) {
927 import_data.import_scripts.emplace(script); // Special rule for IsMine: native P2WPKH requires the TOP script imported (see script/ismine.cpp)
928 }
929 return "";
930 }

Callers 1

ProcessImportLegacyFunction · 0.85

Calls 11

SolverFunction · 0.85
JSONRPCErrorFunction · 0.85
CScriptIDClass · 0.85
CRIPEMD160Class · 0.85
CKeyIDClass · 0.50
uint160Class · 0.50
GetIDMethod · 0.45
sizeMethod · 0.45
FinalizeMethod · 0.45
WriteMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected