diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 0b0a83a58..1b24b5564 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1,1196 +1,1201 @@
 // Copyright (c) 2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include "base58.h"
 #include "chain.h"
 #include "coins.h"
 #include "config.h"
 #include "consensus/validation.h"
 #include "core_io.h"
 #include "dstencode.h"
 #include "init.h"
 #include "keystore.h"
 #include "merkleblock.h"
 #include "net.h"
 #include "policy/policy.h"
 #include "primitives/transaction.h"
 #include "rpc/server.h"
 #include "rpc/tojson.h"
 #include "script/script.h"
 #include "script/script_error.h"
 #include "script/sign.h"
 #include "script/standard.h"
 #include "txmempool.h"
 #include "uint256.h"
 #include "utilstrencodings.h"
 #include "validation.h"
 #ifdef ENABLE_WALLET
 #include "wallet/rpcwallet.h"
 #include "wallet/wallet.h"
 #endif
 
 #include <cstdint>
 
 #include <univalue.h>
 
 void ScriptPubKeyToJSON(const Config &config, const CScript &scriptPubKey,
                         UniValue &out, bool fIncludeHex) {
     txnouttype type;
     std::vector<CTxDestination> addresses;
     int nRequired;
 
     out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey)));
     if (fIncludeHex) {
         out.push_back(
             Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
     }
 
     if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
         out.push_back(Pair("type", GetTxnOutputType(type)));
         return;
     }
 
     out.push_back(Pair("reqSigs", nRequired));
     out.push_back(Pair("type", GetTxnOutputType(type)));
 
     UniValue a(UniValue::VARR);
     for (const CTxDestination &addr : addresses) {
         a.push_back(EncodeDestination(addr));
     }
 
     out.push_back(Pair("addresses", a));
 }
 
 void TxToJSON(const Config &config, const CTransaction &tx,
               const uint256 hashBlock, UniValue &entry) {
     entry.push_back(Pair("txid", tx.GetId().GetHex()));
     entry.push_back(Pair("hash", tx.GetHash().GetHex()));
     entry.push_back(Pair(
         "size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
     entry.push_back(Pair("version", tx.nVersion));
     entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
 
     UniValue vin(UniValue::VARR);
     for (unsigned int i = 0; i < tx.vin.size(); i++) {
         const CTxIn &txin = tx.vin[i];
         UniValue in(UniValue::VOBJ);
         if (tx.IsCoinBase()) {
             in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(),
                                                  txin.scriptSig.end())));
         } else {
             in.push_back(Pair("txid", txin.prevout.GetTxId().GetHex()));
             in.push_back(Pair("vout", int64_t(txin.prevout.GetN())));
             UniValue o(UniValue::VOBJ);
             o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true)));
             o.push_back(Pair(
                 "hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
             in.push_back(Pair("scriptSig", o));
         }
 
         in.push_back(Pair("sequence", (int64_t)txin.nSequence));
         vin.push_back(in);
     }
 
     entry.push_back(Pair("vin", vin));
     UniValue vout(UniValue::VARR);
     for (unsigned int i = 0; i < tx.vout.size(); i++) {
         const CTxOut &txout = tx.vout[i];
         UniValue out(UniValue::VOBJ);
         out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
         out.push_back(Pair("n", (int64_t)i));
         UniValue o(UniValue::VOBJ);
         ScriptPubKeyToJSON(config, txout.scriptPubKey, o, true);
         out.push_back(Pair("scriptPubKey", o));
         vout.push_back(out);
     }
 
     entry.push_back(Pair("vout", vout));
 
     if (!hashBlock.IsNull()) {
         entry.push_back(Pair("blockhash", hashBlock.GetHex()));
         BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
         if (mi != mapBlockIndex.end() && (*mi).second) {
             CBlockIndex *pindex = (*mi).second;
             if (chainActive.Contains(pindex)) {
                 entry.push_back(
                     Pair("confirmations",
                          1 + chainActive.Height() - pindex->nHeight));
                 entry.push_back(Pair("time", pindex->GetBlockTime()));
                 entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
             } else {
                 entry.push_back(Pair("confirmations", 0));
             }
         }
     }
 }
 
 static UniValue getrawtransaction(const Config &config,
                                   const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() < 1 ||
         request.params.size() > 2) {
         throw std::runtime_error(
             "getrawtransaction \"txid\" ( verbose )\n"
 
             "\nNOTE: By default this function only works for mempool "
             "transactions. If the -txindex option is\n"
             "enabled, it also works for blockchain transactions.\n"
             "DEPRECATED: for now, it also works for transactions with unspent "
             "outputs.\n"
 
             "\nReturn the raw transaction data.\n"
             "\nIf verbose is 'true', returns an Object with information about "
             "'txid'.\n"
             "If verbose is 'false' or omitted, returns a string that is "
             "serialized, hex-encoded data for 'txid'.\n"
 
             "\nArguments:\n"
             "1. \"txid\"      (string, required) The transaction id\n"
             "2. verbose       (bool, optional, default=false) If false, return "
             "a string, otherwise return a json object\n"
 
             "\nResult (if verbose is not set or set to false):\n"
             "\"data\"      (string) The serialized, hex-encoded data for "
             "'txid'\n"
 
             "\nResult (if verbose is set to true):\n"
             "{\n"
             "  \"hex\" : \"data\",       (string) The serialized, hex-encoded "
             "data for 'txid'\n"
             "  \"txid\" : \"id\",        (string) The transaction id (same as "
             "provided)\n"
             "  \"hash\" : \"id\",        (string) The transaction hash "
             "(differs from txid for witness transactions)\n"
             "  \"size\" : n,             (numeric) The serialized transaction "
             "size\n"
             "  \"version\" : n,          (numeric) The version\n"
             "  \"locktime\" : ttt,       (numeric) The lock time\n"
             "  \"vin\" : [               (array of json objects)\n"
             "     {\n"
             "       \"txid\": \"id\",    (string) The transaction id\n"
             "       \"vout\": n,         (numeric) \n"
             "       \"scriptSig\": {     (json object) The script\n"
             "         \"asm\": \"asm\",  (string) asm\n"
             "         \"hex\": \"hex\"   (string) hex\n"
             "       },\n"
             "       \"sequence\": n      (numeric) The script sequence number\n"
             "     }\n"
             "     ,...\n"
             "  ],\n"
             "  \"vout\" : [              (array of json objects)\n"
             "     {\n"
             "       \"value\" : x.xxx,            (numeric) The value in " +
             CURRENCY_UNIT +
             "\n"
             "       \"n\" : n,                    (numeric) index\n"
             "       \"scriptPubKey\" : {          (json object)\n"
             "         \"asm\" : \"asm\",          (string) the asm\n"
             "         \"hex\" : \"hex\",          (string) the hex\n"
             "         \"reqSigs\" : n,            (numeric) The required sigs\n"
             "         \"type\" : \"pubkeyhash\",  (string) The type, eg "
             "'pubkeyhash'\n"
             "         \"addresses\" : [           (json array of string)\n"
             "           \"address\"        (string) bitcoin address\n"
             "           ,...\n"
             "         ]\n"
             "       }\n"
             "     }\n"
             "     ,...\n"
             "  ],\n"
             "  \"blockhash\" : \"hash\",   (string) the block hash\n"
             "  \"confirmations\" : n,      (numeric) The confirmations\n"
             "  \"time\" : ttt,             (numeric) The transaction time in "
             "seconds since epoch (Jan 1 1970 GMT)\n"
             "  \"blocktime\" : ttt         (numeric) The block time in seconds "
             "since epoch (Jan 1 1970 GMT)\n"
             "}\n"
 
             "\nExamples:\n" +
             HelpExampleCli("getrawtransaction", "\"mytxid\"") +
             HelpExampleCli("getrawtransaction", "\"mytxid\" true") +
             HelpExampleRpc("getrawtransaction", "\"mytxid\", true"));
     }
 
     LOCK(cs_main);
 
     TxId txid = TxId(ParseHashV(request.params[0], "parameter 1"));
 
     // Accept either a bool (true) or a num (>=1) to indicate verbose output.
     bool fVerbose = false;
     if (request.params.size() > 1) {
         if (request.params[1].isNum()) {
             if (request.params[1].get_int() != 0) {
                 fVerbose = true;
             }
         } else if (request.params[1].isBool()) {
             if (request.params[1].isTrue()) {
                 fVerbose = true;
             }
         } else {
             throw JSONRPCError(
                 RPC_TYPE_ERROR,
                 "Invalid type provided. Verbose parameter must be a boolean.");
         }
     }
 
     CTransactionRef tx;
     uint256 hashBlock;
     if (!GetTransaction(config, txid, tx, hashBlock, true)) {
         throw JSONRPCError(
             RPC_INVALID_ADDRESS_OR_KEY,
             std::string(fTxIndex ? "No such mempool or blockchain transaction"
                                  : "No such mempool transaction. Use -txindex "
                                    "to enable blockchain transaction queries") +
                 ". Use gettransaction for wallet transactions.");
     }
 
     std::string strHex = EncodeHexTx(*tx, RPCSerializationFlags());
 
     if (!fVerbose) {
         return strHex;
     }
 
     UniValue result(UniValue::VOBJ);
     result.push_back(Pair("hex", strHex));
     TxToJSON(config, *tx, hashBlock, result);
     return result;
 }
 
 static UniValue gettxoutproof(const Config &config,
                               const JSONRPCRequest &request) {
     if (request.fHelp ||
         (request.params.size() != 1 && request.params.size() != 2)) {
         throw std::runtime_error(
             "gettxoutproof [\"txid\",...] ( blockhash )\n"
             "\nReturns a hex-encoded proof that \"txid\" was included in a "
             "block.\n"
             "\nNOTE: By default this function only works sometimes. This is "
             "when there is an\n"
             "unspent output in the utxo for this transaction. To make it "
             "always work,\n"
             "you need to maintain a transaction index, using the -txindex "
             "command line option or\n"
             "specify the block in which the transaction is included manually "
             "(by blockhash).\n"
             "\nArguments:\n"
             "1. \"txids\"       (string) A json array of txids to filter\n"
             "    [\n"
             "      \"txid\"     (string) A transaction hash\n"
             "      ,...\n"
             "    ]\n"
             "2. \"blockhash\"   (string, optional) If specified, looks for "
             "txid in the block with this hash\n"
             "\nResult:\n"
             "\"data\"           (string) A string that is a serialized, "
             "hex-encoded data for the proof.\n");
     }
 
     std::set<TxId> setTxIds;
     TxId oneTxId;
     UniValue txids = request.params[0].get_array();
     for (unsigned int idx = 0; idx < txids.size(); idx++) {
         const UniValue &utxid = txids[idx];
         if (utxid.get_str().length() != 64 || !IsHex(utxid.get_str())) {
             throw JSONRPCError(RPC_INVALID_PARAMETER,
                                std::string("Invalid txid ") + utxid.get_str());
         }
 
         TxId txid(uint256S(utxid.get_str()));
         if (setTxIds.count(txid)) {
             throw JSONRPCError(
                 RPC_INVALID_PARAMETER,
                 std::string("Invalid parameter, duplicated txid: ") +
                     utxid.get_str());
         }
 
         setTxIds.insert(txid);
         oneTxId = txid;
     }
 
     LOCK(cs_main);
 
     CBlockIndex *pblockindex = nullptr;
 
     uint256 hashBlock;
     if (request.params.size() > 1) {
         hashBlock = uint256S(request.params[1].get_str());
         if (!mapBlockIndex.count(hashBlock))
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
         pblockindex = mapBlockIndex[hashBlock];
     } else {
         // Loop through txids and try to find which block they're in. Exit loop
         // once a block is found.
         for (const auto &txid : setTxIds) {
             const Coin &coin = AccessByTxid(*pcoinsTip, txid);
             if (!coin.IsSpent()) {
                 pblockindex = chainActive[coin.GetHeight()];
                 break;
             }
         }
     }
 
     if (pblockindex == nullptr) {
         CTransactionRef tx;
         if (!GetTransaction(config, oneTxId, tx, hashBlock, false) ||
             hashBlock.IsNull()) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                "Transaction not yet in block");
         }
 
         if (!mapBlockIndex.count(hashBlock)) {
             throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
         }
 
         pblockindex = mapBlockIndex[hashBlock];
     }
 
     CBlock block;
     if (!ReadBlockFromDisk(block, pblockindex, config)) {
         throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
     }
 
     unsigned int ntxFound = 0;
     for (const auto &tx : block.vtx) {
         if (setTxIds.count(tx->GetId())) {
             ntxFound++;
         }
     }
 
     if (ntxFound != setTxIds.size()) {
         throw JSONRPCError(
             RPC_INVALID_ADDRESS_OR_KEY,
             "Not all transactions found in specified or retrieved block");
     }
 
     CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION);
     CMerkleBlock mb(block, setTxIds);
     ssMB << mb;
     std::string strHex = HexStr(ssMB.begin(), ssMB.end());
     return strHex;
 }
 
 static UniValue verifytxoutproof(const Config &config,
                                  const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() != 1) {
         throw std::runtime_error(
             "verifytxoutproof \"proof\"\n"
             "\nVerifies that a proof points to a transaction in a block, "
             "returning the transaction it commits to\n"
             "and throwing an RPC error if the block is not in our best chain\n"
             "\nArguments:\n"
             "1. \"proof\"    (string, required) The hex-encoded proof "
             "generated by gettxoutproof\n"
             "\nResult:\n"
             "[\"txid\"]      (array, strings) The txid(s) which the proof "
             "commits to, or empty array if the proof is invalid\n");
     }
 
     CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK,
                      PROTOCOL_VERSION);
     CMerkleBlock merkleBlock;
     ssMB >> merkleBlock;
 
     UniValue res(UniValue::VARR);
 
     std::vector<uint256> vMatch;
     std::vector<unsigned int> vIndex;
     if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) !=
         merkleBlock.header.hashMerkleRoot) {
         return res;
     }
 
     LOCK(cs_main);
 
     if (!mapBlockIndex.count(merkleBlock.header.GetHash()) ||
         !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()])) {
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                            "Block not found in chain");
     }
 
     for (const uint256 &hash : vMatch) {
         res.push_back(hash.GetHex());
     }
 
     return res;
 }
 
 static UniValue createrawtransaction(const Config &config,
                                      const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() < 2 ||
         request.params.size() > 3) {
         throw std::runtime_error(
             "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] "
             "{\"address\":amount,\"data\":\"hex\",...} ( locktime )\n"
             "\nCreate a transaction spending the given inputs and creating new "
             "outputs.\n"
             "Outputs can be addresses or data.\n"
             "Returns hex-encoded raw transaction.\n"
             "Note that the transaction's inputs are not signed, and\n"
             "it is not stored in the wallet or transmitted to the network.\n"
 
             "\nArguments:\n"
             "1. \"inputs\"                (array, required) A json array of "
             "json objects\n"
             "     [\n"
             "       {\n"
             "         \"txid\":\"id\",    (string, required) The transaction "
             "id\n"
             "         \"vout\":n,         (numeric, required) The output "
             "number\n"
             "         \"sequence\":n      (numeric, optional) The sequence "
             "number\n"
             "       } \n"
             "       ,...\n"
             "     ]\n"
             "2. \"outputs\"               (object, required) a json object "
             "with outputs\n"
             "    {\n"
             "      \"address\": x.xxx,    (numeric or string, required) The "
             "key is the bitcoin address, the numeric value (can be string) is "
             "the " +
             CURRENCY_UNIT +
             " amount\n"
             "      \"data\": \"hex\"      (string, required) The key is "
             "\"data\", the value is hex encoded data\n"
             "      ,...\n"
             "    }\n"
             "3. locktime                  (numeric, optional, default=0) Raw "
             "locktime. Non-0 value also locktime-activates inputs\n"
             "\nResult:\n"
             "\"transaction\"              (string) hex string of the "
             "transaction\n"
 
             "\nExamples:\n" +
             HelpExampleCli("createrawtransaction",
                            "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" "
                            "\"{\\\"address\\\":0.01}\"") +
             HelpExampleCli("createrawtransaction",
                            "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" "
                            "\"{\\\"data\\\":\\\"00010203\\\"}\"") +
             HelpExampleRpc("createrawtransaction",
                            "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", "
                            "\"{\\\"address\\\":0.01}\"") +
             HelpExampleRpc("createrawtransaction",
                            "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", "
                            "\"{\\\"data\\\":\\\"00010203\\\"}\""));
     }
 
     RPCTypeCheck(request.params,
                  {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true);
     if (request.params[0].isNull() || request.params[1].isNull()) {
         throw JSONRPCError(
             RPC_INVALID_PARAMETER,
             "Invalid parameter, arguments 1 and 2 must be non-null");
     }
 
     UniValue inputs = request.params[0].get_array();
     UniValue sendTo = request.params[1].get_obj();
 
     CMutableTransaction rawTx;
 
     if (request.params.size() > 2 && !request.params[2].isNull()) {
         int64_t nLockTime = request.params[2].get_int64();
         if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max()) {
             throw JSONRPCError(RPC_INVALID_PARAMETER,
                                "Invalid parameter, locktime out of range");
         }
 
         rawTx.nLockTime = nLockTime;
     }
 
     for (size_t idx = 0; idx < inputs.size(); idx++) {
         const UniValue &input = inputs[idx];
         const UniValue &o = input.get_obj();
 
         uint256 txid = ParseHashO(o, "txid");
 
         const UniValue &vout_v = find_value(o, "vout");
-        if (!vout_v.isNum()) {
+        if (vout_v.isNull()) {
             throw JSONRPCError(RPC_INVALID_PARAMETER,
                                "Invalid parameter, missing vout key");
         }
 
+        if (!vout_v.isNum()) {
+            throw JSONRPCError(RPC_INVALID_PARAMETER,
+                               "Invalid parameter, vout must be a number");
+        }
+
         int nOutput = vout_v.get_int();
         if (nOutput < 0) {
             throw JSONRPCError(RPC_INVALID_PARAMETER,
                                "Invalid parameter, vout must be positive");
         }
 
         uint32_t nSequence =
             (rawTx.nLockTime ? std::numeric_limits<uint32_t>::max() - 1
                              : std::numeric_limits<uint32_t>::max());
 
         // Set the sequence number if passed in the parameters object.
         const UniValue &sequenceObj = find_value(o, "sequence");
         if (sequenceObj.isNum()) {
             int64_t seqNr64 = sequenceObj.get_int64();
             if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
                 throw JSONRPCError(
                     RPC_INVALID_PARAMETER,
                     "Invalid parameter, sequence number is out of range");
             }
 
             nSequence = uint32_t(seqNr64);
         }
 
         CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
         rawTx.vin.push_back(in);
     }
 
     std::set<CTxDestination> destinations;
     std::vector<std::string> addrList = sendTo.getKeys();
     for (const std::string &name_ : addrList) {
         if (name_ == "data") {
             std::vector<uint8_t> data =
                 ParseHexV(sendTo[name_].getValStr(), "Data");
 
             CTxOut out(Amount(0), CScript() << OP_RETURN << data);
             rawTx.vout.push_back(out);
         } else {
             CTxDestination destination =
                 DecodeDestination(name_, config.GetChainParams());
             if (!IsValidDestination(destination)) {
                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                    std::string("Invalid Bitcoin address: ") +
                                        name_);
             }
 
             if (!destinations.insert(destination).second) {
                 throw JSONRPCError(
                     RPC_INVALID_PARAMETER,
                     std::string("Invalid parameter, duplicated address: ") +
                         name_);
             }
 
             CScript scriptPubKey = GetScriptForDestination(destination);
             Amount nAmount = AmountFromValue(sendTo[name_]);
 
             CTxOut out(nAmount, scriptPubKey);
             rawTx.vout.push_back(out);
         }
     }
 
     return EncodeHexTx(CTransaction(rawTx));
 }
 
 static UniValue decoderawtransaction(const Config &config,
                                      const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() != 1) {
         throw std::runtime_error(
             "decoderawtransaction \"hexstring\"\n"
             "\nReturn a JSON object representing the serialized, hex-encoded "
             "transaction.\n"
 
             "\nArguments:\n"
             "1. \"hexstring\"      (string, required) The transaction hex "
             "string\n"
 
             "\nResult:\n"
             "{\n"
             "  \"txid\" : \"id\",        (string) The transaction id\n"
             "  \"hash\" : \"id\",        (string) The transaction hash "
             "(differs from txid for witness transactions)\n"
             "  \"size\" : n,             (numeric) The transaction size\n"
             "  \"version\" : n,          (numeric) The version\n"
             "  \"locktime\" : ttt,       (numeric) The lock time\n"
             "  \"vin\" : [               (array of json objects)\n"
             "     {\n"
             "       \"txid\": \"id\",    (string) The transaction id\n"
             "       \"vout\": n,         (numeric) The output number\n"
             "       \"scriptSig\": {     (json object) The script\n"
             "         \"asm\": \"asm\",  (string) asm\n"
             "         \"hex\": \"hex\"   (string) hex\n"
             "       },\n"
             "       \"sequence\": n     (numeric) The script sequence number\n"
             "     }\n"
             "     ,...\n"
             "  ],\n"
             "  \"vout\" : [             (array of json objects)\n"
             "     {\n"
             "       \"value\" : x.xxx,            (numeric) The value in " +
             CURRENCY_UNIT +
             "\n"
             "       \"n\" : n,                    (numeric) index\n"
             "       \"scriptPubKey\" : {          (json object)\n"
             "         \"asm\" : \"asm\",          (string) the asm\n"
             "         \"hex\" : \"hex\",          (string) the hex\n"
             "         \"reqSigs\" : n,            (numeric) The required sigs\n"
             "         \"type\" : \"pubkeyhash\",  (string) The type, eg "
             "'pubkeyhash'\n"
             "         \"addresses\" : [           (json array of string)\n"
             "           \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\"   (string) "
             "bitcoin address\n"
             "           ,...\n"
             "         ]\n"
             "       }\n"
             "     }\n"
             "     ,...\n"
             "  ],\n"
             "}\n"
 
             "\nExamples:\n" +
             HelpExampleCli("decoderawtransaction", "\"hexstring\"") +
             HelpExampleRpc("decoderawtransaction", "\"hexstring\""));
     }
 
     LOCK(cs_main);
     RPCTypeCheck(request.params, {UniValue::VSTR});
 
     CMutableTransaction mtx;
 
     if (!DecodeHexTx(mtx, request.params[0].get_str())) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
     }
 
     UniValue result(UniValue::VOBJ);
     TxToJSON(config, CTransaction(std::move(mtx)), uint256(), result);
 
     return result;
 }
 
 static UniValue decodescript(const Config &config,
                              const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() != 1) {
         throw std::runtime_error(
             "decodescript \"hexstring\"\n"
             "\nDecode a hex-encoded script.\n"
             "\nArguments:\n"
             "1. \"hexstring\"     (string) the hex encoded script\n"
             "\nResult:\n"
             "{\n"
             "  \"asm\":\"asm\",   (string) Script public key\n"
             "  \"hex\":\"hex\",   (string) hex encoded public key\n"
             "  \"type\":\"type\", (string) The output type\n"
             "  \"reqSigs\": n,    (numeric) The required signatures\n"
             "  \"addresses\": [   (json array of string)\n"
             "     \"address\"     (string) bitcoin address\n"
             "     ,...\n"
             "  ],\n"
             "  \"p2sh\",\"address\" (string) address of P2SH script wrapping "
             "this redeem script (not returned if the script is already a "
             "P2SH).\n"
             "}\n"
             "\nExamples:\n" +
             HelpExampleCli("decodescript", "\"hexstring\"") +
             HelpExampleRpc("decodescript", "\"hexstring\""));
     }
 
     RPCTypeCheck(request.params, {UniValue::VSTR});
 
     UniValue r(UniValue::VOBJ);
     CScript script;
     if (request.params[0].get_str().size() > 0) {
         std::vector<uint8_t> scriptData(
             ParseHexV(request.params[0], "argument"));
         script = CScript(scriptData.begin(), scriptData.end());
     } else {
         // Empty scripts are valid.
     }
 
     ScriptPubKeyToJSON(config, script, r, false);
 
     UniValue type;
     type = find_value(r, "type");
 
     if (type.isStr() && type.get_str() != "scripthash") {
         // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
         // don't return the address for a P2SH of the P2SH.
         r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script))));
     }
 
     return r;
 }
 
 /**
  * Pushes a JSON object for script verification or signing errors to vErrorsRet.
  */
 static void TxInErrorToJSON(const CTxIn &txin, UniValue &vErrorsRet,
                             const std::string &strMessage) {
     UniValue entry(UniValue::VOBJ);
     entry.push_back(Pair("txid", txin.prevout.GetTxId().ToString()));
     entry.push_back(Pair("vout", uint64_t(txin.prevout.GetN())));
     entry.push_back(Pair("scriptSig",
                          HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
     entry.push_back(Pair("sequence", uint64_t(txin.nSequence)));
     entry.push_back(Pair("error", strMessage));
     vErrorsRet.push_back(entry);
 }
 
 static UniValue signrawtransaction(const Config &config,
                                    const JSONRPCRequest &request) {
 #ifdef ENABLE_WALLET
     CWallet *const pwallet = GetWalletForJSONRPCRequest(request);
 #endif
 
     if (request.fHelp || request.params.size() < 1 ||
         request.params.size() > 4) {
         throw std::runtime_error(
             "signrawtransaction \"hexstring\" ( "
             "[{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\","
             "\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype "
             ")\n"
             "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
             "The second optional argument (may be null) is an array of "
             "previous transaction outputs that\n"
             "this transaction depends on but may not yet be in the block "
             "chain.\n"
             "The third optional argument (may be null) is an array of "
             "base58-encoded private\n"
             "keys that, if given, will be the only keys used to sign the "
             "transaction.\n"
 #ifdef ENABLE_WALLET
             + HelpRequiringPassphrase(pwallet) +
             "\n"
 #endif
 
             "\nArguments:\n"
             "1. \"hexstring\"     (string, required) The transaction hex "
             "string\n"
             "2. \"prevtxs\"       (string, optional) An json array of previous "
             "dependent transaction outputs\n"
             "     [               (json array of json objects, or 'null' if "
             "none provided)\n"
             "       {\n"
             "         \"txid\":\"id\",             (string, required) The "
             "transaction id\n"
             "         \"vout\":n,                  (numeric, required) The "
             "output number\n"
             "         \"scriptPubKey\": \"hex\",   (string, required) script "
             "key\n"
             "         \"redeemScript\": \"hex\",   (string, required for P2SH "
             "or P2WSH) redeem script\n"
             "         \"amount\": value            (numeric, required) The "
             "amount spent\n"
             "       }\n"
             "       ,...\n"
             "    ]\n"
             "3. \"privkeys\"     (string, optional) A json array of "
             "base58-encoded private keys for signing\n"
             "    [                  (json array of strings, or 'null' if none "
             "provided)\n"
             "      \"privatekey\"   (string) private key in base58-encoding\n"
             "      ,...\n"
             "    ]\n"
             "4. \"sighashtype\"     (string, optional, default=ALL) The "
             "signature hash type. Must be one of\n"
             "       \"ALL\"\n"
             "       \"NONE\"\n"
             "       \"SINGLE\"\n"
             "       \"ALL|ANYONECANPAY\"\n"
             "       \"NONE|ANYONECANPAY\"\n"
             "       \"SINGLE|ANYONECANPAY\"\n"
             "       \"ALL|FORKID\"\n"
             "       \"NONE|FORKID\"\n"
             "       \"SINGLE|FORKID\"\n"
             "       \"ALL|FORKID|ANYONECANPAY\"\n"
             "       \"NONE|FORKID|ANYONECANPAY\"\n"
             "       \"SINGLE|FORKID|ANYONECANPAY\"\n"
 
             "\nResult:\n"
             "{\n"
             "  \"hex\" : \"value\",           (string) The hex-encoded raw "
             "transaction with signature(s)\n"
             "  \"complete\" : true|false,   (boolean) If the transaction has a "
             "complete set of signatures\n"
             "  \"errors\" : [                 (json array of objects) Script "
             "verification errors (if there are any)\n"
             "    {\n"
             "      \"txid\" : \"hash\",           (string) The hash of the "
             "referenced, previous transaction\n"
             "      \"vout\" : n,                (numeric) The index of the "
             "output to spent and used as input\n"
             "      \"scriptSig\" : \"hex\",       (string) The hex-encoded "
             "signature script\n"
             "      \"sequence\" : n,            (numeric) Script sequence "
             "number\n"
             "      \"error\" : \"text\"           (string) Verification or "
             "signing error related to the input\n"
             "    }\n"
             "    ,...\n"
             "  ]\n"
             "}\n"
 
             "\nExamples:\n" +
             HelpExampleCli("signrawtransaction", "\"myhex\"") +
             HelpExampleRpc("signrawtransaction", "\"myhex\""));
     }
 
 #ifdef ENABLE_WALLET
     LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr);
 #else
     LOCK(cs_main);
 #endif
     RPCTypeCheck(
         request.params,
         {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
 
     std::vector<uint8_t> txData(ParseHexV(request.params[0], "argument 1"));
     CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
     std::vector<CMutableTransaction> txVariants;
     while (!ssData.empty()) {
         try {
             CMutableTransaction tx;
             ssData >> tx;
             txVariants.push_back(tx);
         } catch (const std::exception &) {
             throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
         }
     }
 
     if (txVariants.empty()) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction");
     }
 
     // mergedTx will end up with all the signatures; it starts as a clone of the
     // rawtx:
     CMutableTransaction mergedTx(txVariants[0]);
 
     // Fetch previous transactions (inputs):
     CCoinsView viewDummy;
     CCoinsViewCache view(&viewDummy);
     {
         LOCK(mempool.cs);
         CCoinsViewCache &viewChain = *pcoinsTip;
         CCoinsViewMemPool viewMempool(&viewChain, mempool);
         // Temporarily switch cache backend to db+mempool view.
         view.SetBackend(viewMempool);
 
         for (const CTxIn &txin : mergedTx.vin) {
             // Load entries from viewChain into view; can fail.
             view.AccessCoin(txin.prevout);
         }
 
         // Switch back to avoid locking mempool for too long.
         view.SetBackend(viewDummy);
     }
 
     bool fGivenKeys = false;
     CBasicKeyStore tempKeystore;
     if (request.params.size() > 2 && !request.params[2].isNull()) {
         fGivenKeys = true;
         UniValue keys = request.params[2].get_array();
         for (size_t idx = 0; idx < keys.size(); idx++) {
             UniValue k = keys[idx];
             CBitcoinSecret vchSecret;
             bool fGood = vchSecret.SetString(k.get_str());
             if (!fGood) {
                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                    "Invalid private key");
             }
 
             CKey key = vchSecret.GetKey();
             if (!key.IsValid()) {
                 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                    "Private key outside allowed range");
             }
 
             tempKeystore.AddKey(key);
         }
     }
 #ifdef ENABLE_WALLET
     else if (pwallet) {
         EnsureWalletIsUnlocked(pwallet);
     }
 #endif
 
     // Add previous txouts given in the RPC call:
     if (request.params.size() > 1 && !request.params[1].isNull()) {
         UniValue prevTxs = request.params[1].get_array();
         for (size_t idx = 0; idx < prevTxs.size(); idx++) {
             const UniValue &p = prevTxs[idx];
             if (!p.isObject()) {
                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                    "expected object with "
                                    "{\"txid'\",\"vout\",\"scriptPubKey\"}");
             }
 
             UniValue prevOut = p.get_obj();
 
             RPCTypeCheckObj(prevOut,
                             {
                                 {"txid", UniValueType(UniValue::VSTR)},
                                 {"vout", UniValueType(UniValue::VNUM)},
                                 {"scriptPubKey", UniValueType(UniValue::VSTR)},
                                 // "amount" is also required but check is done
                                 // below due to UniValue::VNUM erroneously
                                 // not accepting quoted numerics
                                 // (which are valid JSON)
                             });
 
             uint256 txid = ParseHashO(prevOut, "txid");
 
             int nOut = find_value(prevOut, "vout").get_int();
             if (nOut < 0) {
                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                    "vout must be positive");
             }
 
             COutPoint out(txid, nOut);
             std::vector<uint8_t> pkData(ParseHexO(prevOut, "scriptPubKey"));
             CScript scriptPubKey(pkData.begin(), pkData.end());
 
             {
                 const Coin &coin = view.AccessCoin(out);
                 if (!coin.IsSpent() &&
                     coin.GetTxOut().scriptPubKey != scriptPubKey) {
                     std::string err("Previous output scriptPubKey mismatch:\n");
                     err = err + ScriptToAsmStr(coin.GetTxOut().scriptPubKey) +
                           "\nvs:\n" + ScriptToAsmStr(scriptPubKey);
                     throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
                 }
 
                 CTxOut txout;
                 txout.scriptPubKey = scriptPubKey;
                 txout.nValue = Amount(0);
                 if (prevOut.exists("amount")) {
                     txout.nValue =
                         AmountFromValue(find_value(prevOut, "amount"));
                 } else {
                     // amount param is required in replay-protected txs.
                     // Note that we must check for its presence here rather
                     // than use RPCTypeCheckObj() above, since UniValue::VNUM
                     // parser incorrectly parses numerics with quotes, eg
                     // "3.12" as a string when JSON allows it to also parse
                     // as numeric. And we have to accept numerics with quotes
                     // because our own dogfood (our rpc results) always
                     // produces decimal numbers that are quoted
                     // eg getbalance returns "3.14152" rather than 3.14152
                     throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing amount");
                 }
 
                 view.AddCoin(out, Coin(txout, 1, false), true);
             }
 
             // If redeemScript given and not using the local wallet (private
             // keys given), add redeemScript to the tempKeystore so it can be
             // signed:
             if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
                 RPCTypeCheckObj(
                     prevOut,
                     {
                         {"txid", UniValueType(UniValue::VSTR)},
                         {"vout", UniValueType(UniValue::VNUM)},
                         {"scriptPubKey", UniValueType(UniValue::VSTR)},
                         {"redeemScript", UniValueType(UniValue::VSTR)},
                     });
                 UniValue v = find_value(prevOut, "redeemScript");
                 if (!v.isNull()) {
                     std::vector<uint8_t> rsData(ParseHexV(v, "redeemScript"));
                     CScript redeemScript(rsData.begin(), rsData.end());
                     tempKeystore.AddCScript(redeemScript);
                 }
             }
         }
     }
 
 #ifdef ENABLE_WALLET
     const CKeyStore &keystore =
         ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet);
 #else
     const CKeyStore &keystore = tempKeystore;
 #endif
 
     SigHashType sigHashType = SigHashType().withForkId();
     if (request.params.size() > 3 && !request.params[3].isNull()) {
         static std::map<std::string, int> mapSigHashValues = {
             {"ALL", SIGHASH_ALL},
             {"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY},
             {"ALL|FORKID", SIGHASH_ALL | SIGHASH_FORKID},
             {"ALL|FORKID|ANYONECANPAY",
              SIGHASH_ALL | SIGHASH_FORKID | SIGHASH_ANYONECANPAY},
             {"NONE", SIGHASH_NONE},
             {"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY},
             {"NONE|FORKID", SIGHASH_NONE | SIGHASH_FORKID},
             {"NONE|FORKID|ANYONECANPAY",
              SIGHASH_NONE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY},
             {"SINGLE", SIGHASH_SINGLE},
             {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY},
             {"SINGLE|FORKID", SIGHASH_SINGLE | SIGHASH_FORKID},
             {"SINGLE|FORKID|ANYONECANPAY",
              SIGHASH_SINGLE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY},
         };
         std::string strHashType = request.params[3].get_str();
         if (!mapSigHashValues.count(strHashType)) {
             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param");
         }
 
         sigHashType = SigHashType(mapSigHashValues[strHashType]);
         if (!sigHashType.hasForkId()) {
             throw JSONRPCError(RPC_INVALID_PARAMETER,
                                "Signature must use SIGHASH_FORKID");
         }
     }
 
     // Script verification errors.
     UniValue vErrors(UniValue::VARR);
 
     // Use CTransaction for the constant parts of the transaction to avoid
     // rehashing.
     const CTransaction txConst(mergedTx);
     // Sign what we can:
     for (size_t i = 0; i < mergedTx.vin.size(); i++) {
         CTxIn &txin = mergedTx.vin[i];
         const Coin &coin = view.AccessCoin(txin.prevout);
         if (coin.IsSpent()) {
             TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
             continue;
         }
 
         const CScript &prevPubKey = coin.GetTxOut().scriptPubKey;
         const Amount amount = coin.GetTxOut().nValue;
 
         SignatureData sigdata;
         // Only sign SIGHASH_SINGLE if there's a corresponding output:
         if ((sigHashType.getBaseType() != BaseSigHashType::SINGLE) ||
             (i < mergedTx.vout.size())) {
             ProduceSignature(MutableTransactionSignatureCreator(
                                  &keystore, &mergedTx, i, amount, sigHashType),
                              prevPubKey, sigdata);
         }
 
         // ... and merge in other signatures:
         for (const CMutableTransaction &txv : txVariants) {
             if (txv.vin.size() > i) {
                 sigdata = CombineSignatures(
                     prevPubKey,
                     TransactionSignatureChecker(&txConst, i, amount), sigdata,
                     DataFromTransaction(txv, i));
             }
         }
 
         UpdateTransaction(mergedTx, i, sigdata);
 
         ScriptError serror = SCRIPT_ERR_OK;
         if (!VerifyScript(
                 txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS,
                 TransactionSignatureChecker(&txConst, i, amount), &serror)) {
             TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
         }
     }
 
     bool fComplete = vErrors.empty();
 
     UniValue result(UniValue::VOBJ);
     result.push_back(Pair("hex", EncodeHexTx(CTransaction(mergedTx))));
     result.push_back(Pair("complete", fComplete));
     if (!vErrors.empty()) {
         result.push_back(Pair("errors", vErrors));
     }
 
     return result;
 }
 
 static UniValue sendrawtransaction(const Config &config,
                                    const JSONRPCRequest &request) {
     if (request.fHelp || request.params.size() < 1 ||
         request.params.size() > 2) {
         throw std::runtime_error(
             "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
             "\nSubmits raw transaction (serialized, hex-encoded) to local node "
             "and network.\n"
             "\nAlso see createrawtransaction and signrawtransaction calls.\n"
             "\nArguments:\n"
             "1. \"hexstring\"    (string, required) The hex string of the raw "
             "transaction)\n"
             "2. allowhighfees    (boolean, optional, default=false) Allow high "
             "fees\n"
             "\nResult:\n"
             "\"hex\"             (string) The transaction hash in hex\n"
             "\nExamples:\n"
             "\nCreate a transaction\n" +
             HelpExampleCli("createrawtransaction",
                            "\"[{\\\"txid\\\" : "
                            "\\\"mytxid\\\",\\\"vout\\\":0}]\" "
                            "\"{\\\"myaddress\\\":0.01}\"") +
             "Sign the transaction, and get back the hex\n" +
             HelpExampleCli("signrawtransaction", "\"myhex\"") +
             "\nSend the transaction (signed hex)\n" +
             HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
             "\nAs a json rpc call\n" +
             HelpExampleRpc("sendrawtransaction", "\"signedhex\""));
     }
 
     LOCK(cs_main);
     RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
 
     // parse hex string from parameter
     CMutableTransaction mtx;
     if (!DecodeHexTx(mtx, request.params[0].get_str())) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
     }
 
     CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
     const uint256 &txid = tx->GetId();
 
     bool fLimitFree = false;
     Amount nMaxRawTxFee = maxTxFee;
     if (request.params.size() > 1 && request.params[1].get_bool()) {
         nMaxRawTxFee = Amount(0);
     }
 
     CCoinsViewCache &view = *pcoinsTip;
     bool fHaveChain = false;
     for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
         const Coin &existingCoin = view.AccessCoin(COutPoint(txid, o));
         fHaveChain = !existingCoin.IsSpent();
     }
 
     bool fHaveMempool = mempool.exists(txid);
     if (!fHaveMempool && !fHaveChain) {
         // Push to local node and sync with wallets.
         CValidationState state;
         bool fMissingInputs;
         if (!AcceptToMemoryPool(config, mempool, state, std::move(tx),
                                 fLimitFree, &fMissingInputs, false,
                                 nMaxRawTxFee)) {
             if (state.IsInvalid()) {
                 throw JSONRPCError(RPC_TRANSACTION_REJECTED,
                                    strprintf("%i: %s", state.GetRejectCode(),
                                              state.GetRejectReason()));
             } else {
                 if (fMissingInputs) {
                     throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
                 }
 
                 throw JSONRPCError(RPC_TRANSACTION_ERROR,
                                    state.GetRejectReason());
             }
         }
     } else if (fHaveChain) {
         throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN,
                            "transaction already in block chain");
     }
 
     if (!g_connman) {
         throw JSONRPCError(
             RPC_CLIENT_P2P_DISABLED,
             "Error: Peer-to-peer functionality missing or disabled");
     }
 
     CInv inv(MSG_TX, txid);
     g_connman->ForEachNode([&inv](CNode *pnode) { pnode->PushInventory(inv); });
     return txid.GetHex();
 }
 
 // clang-format off
 static const ContextFreeRPCCommand commands[] = {
     //  category            name                      actor (function)        okSafeMode
     //  ------------------- ------------------------  ----------------------  ----------
     { "rawtransactions",    "getrawtransaction",      getrawtransaction,      true,  {"txid","verbose"} },
     { "rawtransactions",    "createrawtransaction",   createrawtransaction,   true,  {"inputs","outputs","locktime"} },
     { "rawtransactions",    "decoderawtransaction",   decoderawtransaction,   true,  {"hexstring"} },
     { "rawtransactions",    "decodescript",           decodescript,           true,  {"hexstring"} },
     { "rawtransactions",    "sendrawtransaction",     sendrawtransaction,     false, {"hexstring","allowhighfees"} },
     { "rawtransactions",    "signrawtransaction",     signrawtransaction,     false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
 
     { "blockchain",         "gettxoutproof",          gettxoutproof,          true,  {"txids", "blockhash"} },
     { "blockchain",         "verifytxoutproof",       verifytxoutproof,       true,  {"proof"} },
 };
 // clang-format on
 
 void RegisterRawTransactionRPCCommands(CRPCTable &t) {
     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
         t.appendCommand(commands[vcidx].name, &commands[vcidx]);
     }
 }
diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py
index 6e2a3046b..a9aec1a96 100755
--- a/test/functional/rawtransactions.py
+++ b/test/functional/rawtransactions.py
@@ -1,212 +1,221 @@
 #!/usr/bin/env python3
 # Copyright (c) 2014-2016 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """rawtranscation RPCs QA test.
 
 # Tests the following RPCs:
 #    - createrawtransaction
 #    - signrawtransaction
 #    - sendrawtransaction
 #    - decoderawtransaction
 #    - getrawtransaction
 """
 
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import *
 
 # Create one-input, one-output, no-fee transaction:
 
 
 class RawTransactionsTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 3
 
     def setup_network(self, split=False):
         super().setup_network()
         connect_nodes_bi(self.nodes, 0, 2)
 
     def run_test(self):
         # prepare some coins for multiple *rawtransaction commands
         self.nodes[2].generate(1)
         self.sync_all()
         self.nodes[0].generate(101)
         self.sync_all()
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
         self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)
         self.sync_all()
         self.nodes[0].generate(5)
         self.sync_all()
 
         #
         # sendrawtransaction with missing input #
         #
         inputs = [
             {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1}]
         # won't exists
         outputs = {self.nodes[0].getnewaddress(): 4.998}
         rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawtx = self.nodes[2].signrawtransaction(rawtx)
 
         # This will raise an exception since there are missing inputs
         assert_raises_rpc_error(
             -25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex'])
 
         #
         # RAW TX MULTISIG TESTS #
         #
         # 2of2 test
         addr1 = self.nodes[2].getnewaddress()
         addr2 = self.nodes[2].getnewaddress()
 
         addr1Obj = self.nodes[2].validateaddress(addr1)
         addr2Obj = self.nodes[2].validateaddress(addr2)
 
         mSigObj = self.nodes[2].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
         mSigObjValid = self.nodes[2].validateaddress(mSigObj)
 
         # use balance deltas instead of absolute values
         bal = self.nodes[2].getbalance()
 
         # send 1.2 BTC to msig adr
         txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
         self.sync_all()
         self.nodes[0].generate(1)
         self.sync_all()
         # node2 has both keys of the 2of2 ms addr., tx should affect the
         # balance
         assert_equal(self.nodes[2].getbalance(), bal + Decimal('1.20000000'))
 
         # 2of3 test from different nodes
         bal = self.nodes[2].getbalance()
         addr1 = self.nodes[1].getnewaddress()
         addr2 = self.nodes[2].getnewaddress()
         addr3 = self.nodes[2].getnewaddress()
 
         addr1Obj = self.nodes[1].validateaddress(addr1)
         addr2Obj = self.nodes[2].validateaddress(addr2)
         addr3Obj = self.nodes[2].validateaddress(addr3)
 
         mSigObj = self.nodes[2].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])
         mSigObjValid = self.nodes[2].validateaddress(mSigObj)
 
         txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
         decTx = self.nodes[0].gettransaction(txId)
         rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
         sPK = rawTx['vout'][0]['scriptPubKey']['hex']
         self.sync_all()
         self.nodes[0].generate(1)
         self.sync_all()
 
         # THIS IS A INCOMPLETE FEATURE
         # NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND
         # COUNT AT BALANCE CALCULATION
         # for now, assume the funds of a 2of3 multisig tx are not marked as
         # spendable
         assert_equal(self.nodes[2].getbalance(), bal)
 
         txDetails = self.nodes[0].gettransaction(txId, True)
         rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
         vout = False
         for outpoint in rawTx['vout']:
             if outpoint['value'] == Decimal('2.20000000'):
                 vout = outpoint
                 break
 
         bal = self.nodes[0].getbalance()
         inputs = [{
             "txid": txId,
             "vout": vout['n'],
             "scriptPubKey": vout['scriptPubKey']['hex'],
             "amount": vout['value'],
         }]
         outputs = {self.nodes[0].getnewaddress(): 2.19}
         rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs)
         # node1 only has one key, can't comp. sign the tx
         assert_equal(rawTxPartialSigned['complete'], False)
 
         rawTxSigned = self.nodes[2].signrawtransaction(rawTx, inputs)
         # node2 can sign the tx compl., own two of three keys
         assert_equal(rawTxSigned['complete'], True)
         self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
         rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
         self.sync_all()
         self.nodes[0].generate(1)
         self.sync_all()
         assert_equal(self.nodes[0].getbalance(), bal + Decimal(
             '50.00000000') + Decimal('2.19000000'))  # block reward + tx
 
         # getrawtransaction tests
         # 1. valid parameters - only supply txid
         txHash = rawTx["hash"]
         assert_equal(
             self.nodes[0].getrawtransaction(txHash), rawTxSigned['hex'])
 
         # 2. valid parameters - supply txid and 0 for non-verbose
         assert_equal(
             self.nodes[0].getrawtransaction(txHash, 0), rawTxSigned['hex'])
 
         # 3. valid parameters - supply txid and False for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(
             txHash, False), rawTxSigned['hex'])
 
         # 4. valid parameters - supply txid and 1 for verbose.
         # We only check the "hex" field of the output so we don't need to
         # update this test every time the output format changes.
         assert_equal(self.nodes[0].getrawtransaction(
             txHash, 1)["hex"], rawTxSigned['hex'])
 
         # 5. valid parameters - supply txid and True for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(
             txHash, True)["hex"], rawTxSigned['hex'])
 
         # 6. invalid parameters - supply txid and string "Flase"
         assert_raises_rpc_error(
             -3, "Invalid type", self.nodes[0].getrawtransaction, txHash, "False")
 
         # 7. invalid parameters - supply txid and empty array
         assert_raises_rpc_error(
             -3, "Invalid type", self.nodes[0].getrawtransaction, txHash, [])
 
         # 8. invalid parameters - supply txid and empty dict
         assert_raises_rpc_error(
             -3, "Invalid type", self.nodes[0].getrawtransaction, txHash, {})
 
         inputs = [
-            {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': 1000}]
+            {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'sequence': 1000}]
         outputs = {self.nodes[0].getnewaddress(): 1}
+        assert_raises_rpc_error(
+            -8, 'Invalid parameter, missing vout key',
+            self.nodes[0].createrawtransaction, inputs, outputs)
+
+        inputs[0]['vout'] = "1"
+        assert_raises_rpc_error(
+            -8, 'Invalid parameter, vout must be a number',
+            self.nodes[0].createrawtransaction, inputs, outputs)
+
+        inputs[0]['vout'] = -1
+        assert_raises_rpc_error(
+            -8, 'Invalid parameter, vout must be positive',
+            self.nodes[0].createrawtransaction, inputs, outputs)
+
+        inputs[0]['vout'] = 1
         rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['vin'][0]['sequence'], 1000)
 
         # 9. invalid parameters - sequence number out of range
-        inputs = [
-            {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': -1}]
-        outputs = {self.nodes[0].getnewaddress(): 1}
+        inputs[0]['sequence'] = -1
         assert_raises_rpc_error(
             -8, 'Invalid parameter, sequence number is out of range',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         # 10. invalid parameters - sequence number out of range
-        inputs = [
-            {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': 4294967296}]
-        outputs = {self.nodes[0].getnewaddress(): 1}
+        inputs[0]['sequence'] = 4294967296
         assert_raises_rpc_error(
             -8, 'Invalid parameter, sequence number is out of range',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
-        inputs = [
-            {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': 4294967294}]
-        outputs = {self.nodes[0].getnewaddress(): 1}
+        inputs[0]['sequence'] = 4294967294
         rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
 
 
 if __name__ == '__main__':
     RawTransactionsTest().main()