| 768 | } |
| 769 | |
| 770 | UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType) |
| 771 | { |
| 772 | // Fetch previous transactions (inputs): |
| 773 | CCoinsView viewDummy; |
| 774 | CCoinsViewCache view(&viewDummy); |
| 775 | { |
| 776 | LOCK2(cs_main, mempool.cs); |
| 777 | CCoinsViewCache &viewChain = *pcoinsTip; |
| 778 | CCoinsViewMemPool viewMempool(&viewChain, mempool); |
| 779 | view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view |
| 780 | |
| 781 | for (const CTxIn& txin : mtx.vin) { |
| 782 | view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail. |
| 783 | } |
| 784 | |
| 785 | view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long |
| 786 | } |
| 787 | |
| 788 | // Add previous txouts given in the RPC call: |
| 789 | if (!prevTxsUnival.isNull()) { |
| 790 | UniValue prevTxs = prevTxsUnival.get_array(); |
| 791 | for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) { |
| 792 | const UniValue& p = prevTxs[idx]; |
| 793 | if (!p.isObject()) { |
| 794 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); |
| 795 | } |
| 796 | |
| 797 | UniValue prevOut = p.get_obj(); |
| 798 | |
| 799 | RPCTypeCheckObj(prevOut, |
| 800 | { |
| 801 | {"txid", UniValueType(UniValue::VSTR)}, |
| 802 | {"vout", UniValueType(UniValue::VNUM)}, |
| 803 | {"scriptPubKey", UniValueType(UniValue::VSTR)}, |
| 804 | }); |
| 805 | |
| 806 | uint256 txid = ParseHashO(prevOut, "txid"); |
| 807 | |
| 808 | int nOut = find_value(prevOut, "vout").get_int(); |
| 809 | if (nOut < 0) { |
| 810 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive"); |
| 811 | } |
| 812 | |
| 813 | COutPoint out(txid, nOut); |
| 814 | std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey")); |
| 815 | CScript scriptPubKey(pkData.begin(), pkData.end()); |
| 816 | |
| 817 | { |
| 818 | const Coin& coin = view.AccessCoin(out); |
| 819 | if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) { |
| 820 | std::string err("Previous output scriptPubKey mismatch:\n"); |
| 821 | err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+ |
| 822 | ScriptToAsmStr(scriptPubKey); |
| 823 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); |
| 824 | } |
| 825 | Coin newcoin; |
| 826 | newcoin.out.scriptPubKey = scriptPubKey; |
| 827 | newcoin.out.nValue = MAX_MONEY; |
no test coverage detected