diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index f634b9f35..56be64d9d 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1,2190 +1,2189 @@
 // 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 <blockdb.h>
 #include <chain.h>
 #include <chainparams.h>
 #include <coins.h>
 #include <config.h>
 #include <consensus/validation.h>
 #include <core_io.h>
 #include <index/txindex.h>
 #include <key_io.h>
 #include <merkleblock.h>
 #include <node/coin.h>
 #include <node/context.h>
 #include <node/psbt.h>
 #include <node/transaction.h>
 #include <policy/policy.h>
 #include <primitives/transaction.h>
 #include <psbt.h>
 #include <random.h>
 #include <rpc/blockchain.h>
 #include <rpc/rawtransaction_util.h>
 #include <rpc/server.h>
 #include <rpc/util.h>
 #include <script/script.h>
 #include <script/sign.h>
 #include <script/signingprovider.h>
 #include <script/standard.h>
 #include <txmempool.h>
 #include <uint256.h>
 #include <util/error.h>
 #include <util/moneystr.h>
 #include <util/strencodings.h>
 #include <validation.h>
 #include <validationinterface.h>
 
 #include <cstdint>
 #include <numeric>
 
 #include <univalue.h>
 
 static void TxToJSON(const CTransaction &tx, const BlockHash &hashBlock,
                      UniValue &entry) {
     // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
     //
     // Blockchain contextual information (confirmations and blocktime) is not
     // available to code in bitcoin-common, so we query them here and push the
     // data into the returned UniValue.
     TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
 
     if (!hashBlock.IsNull()) {
         LOCK(cs_main);
 
         entry.pushKV("blockhash", hashBlock.GetHex());
         CBlockIndex *pindex = LookupBlockIndex(hashBlock);
         if (pindex) {
             if (::ChainActive().Contains(pindex)) {
                 entry.pushKV("confirmations",
                              1 + ::ChainActive().Height() - pindex->nHeight);
                 entry.pushKV("time", pindex->GetBlockTime());
                 entry.pushKV("blocktime", pindex->GetBlockTime());
             } else {
                 entry.pushKV("confirmations", 0);
             }
         }
     }
 }
 
 static UniValue getrawtransaction(const Config &config,
                                   const JSONRPCRequest &request) {
     RPCHelpMan{
         "getrawtransaction",
         "By default this function only works for mempool transactions. When "
         "called with a blockhash\n"
         "argument, getrawtransaction will return the transaction if the "
         "specified block is available and\n"
         "the transaction is found in that block. When called without a "
         "blockhash argument, getrawtransaction\n"
         "will return the transaction if it is in the mempool, or if -txindex "
         "is enabled and the transaction\n"
         "is in a block in the blockchain.\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",
         {
             {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The transaction id"},
             {"verbose", RPCArg::Type::BOOL, /* default */ "false",
              "If false, return a string, otherwise return a json object"},
             {"blockhash", RPCArg::Type::STR_HEX,
              RPCArg::Optional::OMITTED_NAMED_ARG,
              "The block in which to look for the transaction"},
         },
         {
             RPCResult{"if verbose is not set or set to false",
                       RPCResult::Type::STR, "data",
                       "The serialized, hex-encoded data for 'txid'"},
             RPCResult{
                 "if verbose is set to true",
                 RPCResult::Type::OBJ,
                 "",
                 "",
                 {
                     {RPCResult::Type::BOOL, "in_active_chain",
                      "Whether specified block is in the active chain or not "
                      "(only present with explicit \"blockhash\" argument)"},
                     {RPCResult::Type::STR_HEX, "hex",
                      "The serialized, hex-encoded data for 'txid'"},
                     {RPCResult::Type::STR_HEX, "txid",
                      "The transaction id (same as provided)"},
                     {RPCResult::Type::STR_HEX, "hash", "The transaction hash"},
                     {RPCResult::Type::NUM, "size",
                      "The serialized transaction size"},
                     {RPCResult::Type::NUM, "version", "The version"},
                     {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
                     {RPCResult::Type::ARR,
                      "vin",
                      "",
                      {
                          {RPCResult::Type::OBJ,
                           "",
                           "",
                           {
                               {RPCResult::Type::STR_HEX, "txid",
                                "The transaction id"},
                               {RPCResult::Type::STR, "vout", ""},
                               {RPCResult::Type::OBJ,
                                "scriptSig",
                                "The script",
                                {
                                    {RPCResult::Type::STR, "asm", "asm"},
                                    {RPCResult::Type::STR_HEX, "hex", "hex"},
                                }},
                               {RPCResult::Type::NUM, "sequence",
                                "The script sequence number"},
                           }},
                      }},
                     {RPCResult::Type::ARR,
                      "vout",
                      "",
                      {
                          {RPCResult::Type::OBJ,
                           "",
                           "",
                           {
                               {RPCResult::Type::NUM, "value",
                                "The value in " + CURRENCY_UNIT},
                               {RPCResult::Type::NUM, "n", "index"},
                               {RPCResult::Type::OBJ,
                                "scriptPubKey",
                                "",
                                {
                                    {RPCResult::Type::STR, "asm", "the asm"},
                                    {RPCResult::Type::STR, "hex", "the hex"},
                                    {RPCResult::Type::NUM, "reqSigs",
                                     "The required sigs"},
                                    {RPCResult::Type::STR, "type",
                                     "The type, eg 'pubkeyhash'"},
                                    {RPCResult::Type::ARR,
                                     "addresses",
                                     "",
                                     {
                                         {RPCResult::Type::STR, "address",
                                          "bitcoin address"},
                                     }},
                                }},
                           }},
                      }},
                     {RPCResult::Type::STR_HEX, "blockhash", "the block hash"},
                     {RPCResult::Type::NUM, "confirmations",
                      "The confirmations"},
                     {RPCResult::Type::NUM_TIME, "blocktime",
                      "The block time expressed in " + UNIX_EPOCH_TIME},
                     {RPCResult::Type::NUM, "time", "Same as \"blocktime\""},
                 }},
         },
         RPCExamples{HelpExampleCli("getrawtransaction", "\"mytxid\"") +
                     HelpExampleCli("getrawtransaction", "\"mytxid\" true") +
                     HelpExampleRpc("getrawtransaction", "\"mytxid\", true") +
                     HelpExampleCli("getrawtransaction",
                                    "\"mytxid\" false \"myblockhash\"") +
                     HelpExampleCli("getrawtransaction",
                                    "\"mytxid\" true \"myblockhash\"")},
     }
         .Check(request);
 
     bool in_active_chain = true;
     TxId txid = TxId(ParseHashV(request.params[0], "parameter 1"));
     CBlockIndex *blockindex = nullptr;
 
     const CChainParams &params = config.GetChainParams();
     if (txid == params.GenesisBlock().hashMerkleRoot) {
         // Special exception for the genesis block coinbase transaction
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                            "The genesis block coinbase is not considered an "
                            "ordinary transaction and cannot be retrieved");
     }
 
     // Accept either a bool (true) or a num (>=1) to indicate verbose output.
     bool fVerbose = false;
     if (!request.params[1].isNull()) {
         fVerbose = request.params[1].isNum()
                        ? (request.params[1].get_int() != 0)
                        : request.params[1].get_bool();
     }
 
     if (!request.params[2].isNull()) {
         LOCK(cs_main);
 
         BlockHash blockhash(ParseHashV(request.params[2], "parameter 3"));
         blockindex = LookupBlockIndex(blockhash);
         if (!blockindex) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                "Block hash not found");
         }
         in_active_chain = ::ChainActive().Contains(blockindex);
     }
 
     bool f_txindex_ready = false;
     if (g_txindex && !blockindex) {
         f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
     }
 
     CTransactionRef tx;
     BlockHash hash_block;
     if (!GetTransaction(txid, tx, params.GetConsensus(), hash_block,
                         blockindex)) {
         std::string errmsg;
         if (blockindex) {
             if (!blockindex->nStatus.hasData()) {
                 throw JSONRPCError(RPC_MISC_ERROR, "Block not available");
             }
             errmsg = "No such transaction found in the provided block";
         } else if (!g_txindex) {
             errmsg = "No such mempool transaction. Use -txindex to enable "
                      "blockchain transaction queries";
         } else if (!f_txindex_ready) {
             errmsg = "No such mempool transaction. Blockchain transactions are "
                      "still in the process of being indexed";
         } else {
             errmsg = "No such mempool or blockchain transaction";
         }
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                            errmsg +
                                ". Use gettransaction for wallet transactions.");
     }
 
     if (!fVerbose) {
         return EncodeHexTx(*tx, RPCSerializationFlags());
     }
 
     UniValue result(UniValue::VOBJ);
     if (blockindex) {
         result.pushKV("in_active_chain", in_active_chain);
     }
     TxToJSON(*tx, hash_block, result);
     return result;
 }
 
 static UniValue gettxoutproof(const Config &config,
                               const JSONRPCRequest &request) {
     RPCHelpMan{
         "gettxoutproof",
         "Returns 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",
         {
             {
                 "txids",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of txids to filter",
                 {
                     {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED,
                      "A transaction hash"},
                 },
             },
             {"blockhash", RPCArg::Type::STR_HEX,
              RPCArg::Optional::OMITTED_NAMED_ARG,
              "If specified, looks for txid in the block with this hash"},
         },
         RPCResult{
             RPCResult::Type::STR, "data",
             "A string that is a serialized, hex-encoded data for the proof."},
         RPCExamples{""},
     }
         .Check(request);
 
     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];
         TxId txid(ParseHashV(utxid, "txid"));
         if (setTxIds.count(txid)) {
             throw JSONRPCError(
                 RPC_INVALID_PARAMETER,
                 std::string("Invalid parameter, duplicated txid: ") +
                     utxid.get_str());
         }
 
         setTxIds.insert(txid);
         oneTxId = txid;
     }
 
     CBlockIndex *pblockindex = nullptr;
 
     BlockHash hashBlock;
     if (!request.params[1].isNull()) {
         LOCK(cs_main);
         hashBlock = BlockHash(ParseHashV(request.params[1], "blockhash"));
         pblockindex = LookupBlockIndex(hashBlock);
         if (!pblockindex) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
         }
     } else {
         LOCK(cs_main);
         // 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(::ChainstateActive().CoinsTip(), txid);
             if (!coin.IsSpent()) {
                 pblockindex = ::ChainActive()[coin.GetHeight()];
                 break;
             }
         }
     }
 
     // Allow txindex to catch up if we need to query it and before we acquire
     // cs_main.
     if (g_txindex && !pblockindex) {
         g_txindex->BlockUntilSyncedToCurrentChain();
     }
 
     const Consensus::Params &params = config.GetChainParams().GetConsensus();
 
     LOCK(cs_main);
 
     if (pblockindex == nullptr) {
         CTransactionRef tx;
         if (!GetTransaction(oneTxId, tx, params, hashBlock) ||
             hashBlock.IsNull()) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                "Transaction not yet in block");
         }
 
         pblockindex = LookupBlockIndex(hashBlock);
         if (!pblockindex) {
             throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
         }
     }
 
     CBlock block;
     if (!ReadBlockFromDisk(block, pblockindex, params)) {
         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) {
     RPCHelpMan{
         "verifytxoutproof",
         "Verifies 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",
         {
             {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The hex-encoded proof generated by gettxoutproof"},
         },
         RPCResult{RPCResult::Type::ARR,
                   "",
                   "",
                   {
                       {RPCResult::Type::STR_HEX, "txid",
                        "The txid(s) which the proof commits to, or empty array "
                        "if the proof can not be validated."},
                   }},
         RPCExamples{""},
     }
         .Check(request);
 
     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<size_t> vIndex;
     if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) !=
         merkleBlock.header.hashMerkleRoot) {
         return res;
     }
 
     LOCK(cs_main);
 
     const CBlockIndex *pindex = LookupBlockIndex(merkleBlock.header.GetHash());
     if (!pindex || !::ChainActive().Contains(pindex) || pindex->nTx == 0) {
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                            "Block not found in chain");
     }
 
     // Check if proof is valid, only add results if so
     if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) {
         for (const uint256 &hash : vMatch) {
             res.push_back(hash.GetHex());
         }
     }
 
     return res;
 }
 
 static UniValue createrawtransaction(const Config &config,
                                      const JSONRPCRequest &request) {
     RPCHelpMan{
         "createrawtransaction",
         "Create 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",
         {
             {
                 "inputs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of json objects",
                 {
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"txid", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO, "The transaction id"},
                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO,
                              "The output number"},
                             {"sequence", RPCArg::Type::NUM, /* default */
                              "depends on the value of the 'locktime' argument",
                              "The sequence number"},
                         },
                     },
                 },
             },
             {
                 "outputs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "a json array with outputs (key-value pairs), where none of "
                 "the keys are duplicated.\n"
                 "That is, each address can only appear once and there can only "
                 "be one 'data' object.\n"
                 "For compatibility reasons, a dictionary, which holds the "
                 "key-value pairs directly, is also\n"
                 "                             accepted as second parameter.",
                 {
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"address", RPCArg::Type::AMOUNT,
                              RPCArg::Optional::NO,
                              "A key-value pair. The key (string) is the "
                              "bitcoin address, the value (float or string) is "
                              "the amount in " +
                                  CURRENCY_UNIT},
                         },
                     },
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"data", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO,
                              "A key-value pair. The key must be \"data\", the "
                              "value is hex-encoded data"},
                         },
                     },
                 },
             },
             {"locktime", RPCArg::Type::NUM, /* default */ "0",
              "Raw locktime. Non-0 value also locktime-activates inputs"},
         },
         RPCResult{RPCResult::Type::STR_HEX, "transaction",
                   "hex string of the transaction"},
         RPCExamples{
             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\\\"}]\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params,
                  {UniValue::VARR,
                   UniValueType(), // ARR or OBJ, checked later
                   UniValue::VNUM},
                  true);
 
     CMutableTransaction rawTx =
         ConstructTransaction(config.GetChainParams(), request.params[0],
                              request.params[1], request.params[2]);
 
     return EncodeHexTx(CTransaction(rawTx));
 }
 
 static UniValue decoderawtransaction(const Config &config,
                                      const JSONRPCRequest &request) {
     RPCHelpMan{
         "decoderawtransaction",
         "Return a JSON object representing the serialized, hex-encoded "
         "transaction.\n",
         {
             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The transaction hex string"},
         },
         RPCResult{
             RPCResult::Type::OBJ,
             "",
             "",
             {
                 {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
                 {RPCResult::Type::STR_HEX, "hash", "The transaction hash"},
                 {RPCResult::Type::NUM, "size", "The transaction size"},
                 {RPCResult::Type::NUM, "version", "The version"},
                 {RPCResult::Type::NUM_TIME, "locktime", "The lock time"},
                 {RPCResult::Type::ARR,
                  "vin",
                  "",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::STR_HEX, "txid",
                            "The transaction id"},
                           {RPCResult::Type::NUM, "vout", "The output number"},
                           {RPCResult::Type::OBJ,
                            "scriptSig",
                            "The script",
                            {
                                {RPCResult::Type::STR, "asm", "asm"},
                                {RPCResult::Type::STR_HEX, "hex", "hex"},
                            }},
                           {RPCResult::Type::NUM, "sequence",
                            "The script sequence number"},
                       }},
                  }},
                 {RPCResult::Type::ARR,
                  "vout",
                  "",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::NUM, "value",
                            "The value in " + CURRENCY_UNIT},
                           {RPCResult::Type::NUM, "n", "index"},
                           {RPCResult::Type::OBJ,
                            "scriptPubKey",
                            "",
                            {
                                {RPCResult::Type::STR, "asm", "the asm"},
                                {RPCResult::Type::STR_HEX, "hex", "the hex"},
                                {RPCResult::Type::NUM, "reqSigs",
                                 "The required sigs"},
                                {RPCResult::Type::STR, "type",
                                 "The type, eg 'pubkeyhash'"},
                                {RPCResult::Type::ARR,
                                 "addresses",
                                 "",
                                 {
                                     {RPCResult::Type::STR, "address",
                                      "bitcoin address"},
                                 }},
                            }},
                       }},
                  }},
             }},
         RPCExamples{HelpExampleCli("decoderawtransaction", "\"hexstring\"") +
                     HelpExampleRpc("decoderawtransaction", "\"hexstring\"")},
     }
         .Check(request);
 
     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);
     TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false);
 
     return result;
 }
 
 static std::string GetAllOutputTypes() {
     std::string ret;
     for (int i = TX_NONSTANDARD; i <= TX_NULL_DATA; ++i) {
         if (i != TX_NONSTANDARD) {
             ret += ", ";
         }
         ret += GetTxnOutputType(static_cast<txnouttype>(i));
     }
     return ret;
 }
 
 static UniValue decodescript(const Config &config,
                              const JSONRPCRequest &request) {
     RPCHelpMan{
         "decodescript",
         "Decode a hex-encoded script.\n",
         {
             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "the hex-encoded script"},
         },
         RPCResult{
             RPCResult::Type::OBJ,
             "",
             "",
             {
                 {RPCResult::Type::STR, "asm", "Script public key"},
                 {RPCResult::Type::STR, "type",
                  "The output type (e.g. " + GetAllOutputTypes() + ")"},
                 {RPCResult::Type::NUM, "reqSigs", "The required signatures"},
                 {RPCResult::Type::ARR,
                  "addresses",
                  "",
                  {
                      {RPCResult::Type::STR, "address", "bitcoin address"},
                  }},
                 {RPCResult::Type::STR, "p2sh",
                  "address of P2SH script wrapping this redeem script (not "
                  "returned if the script is already a P2SH)"},
             }},
         RPCExamples{HelpExampleCli("decodescript", "\"hexstring\"") +
                     HelpExampleRpc("decodescript", "\"hexstring\"")},
     }
         .Check(request);
 
     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.
     }
 
     ScriptPubKeyToUniv(script, r, /* fIncludeHex */ 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.pushKV("p2sh", EncodeDestination(ScriptHash(script), config));
     }
 
     return r;
 }
 
 static UniValue combinerawtransaction(const Config &config,
                                       const JSONRPCRequest &request) {
     RPCHelpMan{
         "combinerawtransaction",
         "Combine multiple partially signed transactions into one "
         "transaction.\n"
         "The combined transaction may be another partially signed transaction "
         "or a \n"
         "fully signed transaction.",
         {
             {
                 "txs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of hex strings of partially signed "
                 "transactions",
                 {
                     {"hexstring", RPCArg::Type::STR_HEX,
                      RPCArg::Optional::OMITTED, "A transaction hash"},
                 },
             },
         },
         RPCResult{RPCResult::Type::STR, "",
                   "The hex-encoded raw transaction with signature(s)"},
         RPCExamples{HelpExampleCli("combinerawtransaction",
                                    "[\"myhex1\", \"myhex2\", \"myhex3\"]")},
     }
         .Check(request);
 
     UniValue txs = request.params[0].get_array();
     std::vector<CMutableTransaction> txVariants(txs.size());
 
     for (unsigned int idx = 0; idx < txs.size(); idx++) {
         if (!DecodeHexTx(txVariants[idx], txs[idx].get_str())) {
             throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                strprintf("TX decode failed for tx %d", idx));
         }
     }
 
     if (txVariants.empty()) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transactions");
     }
 
     // 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);
     {
         const CTxMemPool &mempool = EnsureMemPool(request.context);
         LOCK(cs_main);
         LOCK(mempool.cs);
         CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
         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);
     }
 
     // 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()) {
             throw JSONRPCError(RPC_VERIFY_ERROR,
                                "Input not found or already spent");
         }
         SignatureData sigdata;
 
         const CTxOut &txout = coin.GetTxOut();
 
         // ... and merge in other signatures:
         for (const CMutableTransaction &txv : txVariants) {
             if (txv.vin.size() > i) {
                 sigdata.MergeSignatureData(DataFromTransaction(txv, i, txout));
             }
         }
         ProduceSignature(
             DUMMY_SIGNING_PROVIDER,
             MutableTransactionSignatureCreator(&mergedTx, i, txout.nValue),
             txout.scriptPubKey, sigdata);
 
         UpdateInput(txin, sigdata);
     }
 
     return EncodeHexTx(CTransaction(mergedTx));
 }
 
 static UniValue signrawtransactionwithkey(const Config &config,
                                           const JSONRPCRequest &request) {
     RPCHelpMan{
         "signrawtransactionwithkey",
         "Sign inputs for raw transaction (serialized, hex-encoded).\n"
         "The second argument is an array of base58-encoded private\n"
         "keys that will be the only keys used to sign the transaction.\n"
         "The third 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",
         {
             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The transaction hex string"},
             {
                 "privkeys",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of base58-encoded private keys for signing",
                 {
                     {"privatekey", RPCArg::Type::STR, RPCArg::Optional::OMITTED,
                      "private key in base58-encoding"},
                 },
             },
             {
                 "prevtxs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::OMITTED_NAMED_ARG,
                 "A json array of previous dependent transaction outputs",
                 {
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"txid", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO, "The transaction id"},
                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO,
                              "The output number"},
                             {"scriptPubKey", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO, "script key"},
                             {"redeemScript", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::OMITTED,
                              "(required for P2SH) redeem script"},
                             {"amount", RPCArg::Type::AMOUNT,
                              RPCArg::Optional::NO, "The amount spent"},
                         },
                     },
                 },
             },
             {"sighashtype", RPCArg::Type::STR, /* default */ "ALL|FORKID",
              "The signature hash type. Must be one of:\n"
              "       \"ALL|FORKID\"\n"
              "       \"NONE|FORKID\"\n"
              "       \"SINGLE|FORKID\"\n"
              "       \"ALL|FORKID|ANYONECANPAY\"\n"
              "       \"NONE|FORKID|ANYONECANPAY\"\n"
              "       \"SINGLE|FORKID|ANYONECANPAY\""},
         },
         RPCResult{
             RPCResult::Type::OBJ,
             "",
             "",
             {
                 {RPCResult::Type::STR_HEX, "hex",
                  "The hex-encoded raw transaction with signature(s)"},
                 {RPCResult::Type::BOOL, "complete",
                  "If the transaction has a complete set of signatures"},
                 {RPCResult::Type::ARR,
                  "errors",
                  "Script verification errors (if there are any)",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::STR_HEX, "txid",
                            "The hash of the referenced, previous transaction"},
                           {RPCResult::Type::NUM, "vout",
                            "The index of the output to spent and used as "
                            "input"},
                           {RPCResult::Type::STR_HEX, "scriptSig",
                            "The hex-encoded signature script"},
                           {RPCResult::Type::NUM, "sequence",
                            "Script sequence number"},
                           {RPCResult::Type::STR, "error",
                            "Verification or signing error related to the "
                            "input"},
                       }},
                  }},
             }},
         RPCExamples{
             HelpExampleCli("signrawtransactionwithkey",
                            "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") +
             HelpExampleRpc("signrawtransactionwithkey",
                            "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"")},
     }
         .Check(request);
 
     RPCTypeCheck(
         request.params,
         {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
 
     CMutableTransaction mtx;
     if (!DecodeHexTx(mtx, request.params[0].get_str())) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
     }
 
     FillableSigningProvider keystore;
     const UniValue &keys = request.params[1].get_array();
     for (size_t idx = 0; idx < keys.size(); ++idx) {
         UniValue k = keys[idx];
         CKey key = DecodeSecret(k.get_str());
         if (!key.IsValid()) {
             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
                                "Invalid private key");
         }
         keystore.AddKey(key);
     }
 
     // Fetch previous transactions (inputs):
     std::map<COutPoint, Coin> coins;
     for (const CTxIn &txin : mtx.vin) {
         // Create empty map entry keyed by prevout.
         coins[txin.prevout];
     }
     NodeContext &node = EnsureNodeContext(request.context);
     FindCoins(node, coins);
 
     // Parse the prevtxs array
     ParsePrevouts(request.params[2], &keystore, coins);
 
     UniValue result(UniValue::VOBJ);
     SignTransaction(mtx, &keystore, coins, request.params[3], result);
     return result;
 }
 
 static UniValue sendrawtransaction(const Config &config,
                                    const JSONRPCRequest &request) {
     RPCHelpMan{
         "sendrawtransaction",
         "Submits raw transaction (serialized, hex-encoded) to local node and "
         "network.\n"
         "\nAlso see createrawtransaction and "
         "signrawtransactionwithkey calls.\n",
         {
             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The hex string of the raw transaction"},
             {"maxfeerate", RPCArg::Type::AMOUNT,
              /* default */
              FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()),
              "Reject transactions whose fee rate is higher than the specified "
              "value, expressed in " +
                  CURRENCY_UNIT + "/kB\nSet to 0 to accept any fee rate.\n"},
         },
         RPCResult{RPCResult::Type::STR_HEX, "", "The transaction hash in hex"},
         RPCExamples{
             "\nCreate a transaction\n" +
             HelpExampleCli(
                 "createrawtransaction",
                 "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" "
                 "\"{\\\"myaddress\\\":0.01}\"") +
             "Sign the transaction, and get back the hex\n" +
             HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             "\nSend the transaction (signed hex)\n" +
             HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
             "\nAs a JSON-RPC call\n" +
             HelpExampleRpc("sendrawtransaction", "\"signedhex\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {
                                      UniValue::VSTR,
                                      // NUM or BOOL, checked later
                                      UniValueType(),
                                  });
 
     // 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)));
 
     CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE;
     // TODO: temporary migration code for old clients. Remove in v0.22
     if (request.params[1].isBool()) {
         throw JSONRPCError(RPC_INVALID_PARAMETER,
                            "Second argument must be numeric (maxfeerate) and "
                            "no longer supports a boolean. To allow a "
                            "transaction with high fees, set maxfeerate to 0.");
     } else if (!request.params[1].isNull()) {
         max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1]));
     }
 
     int64_t virtual_size = GetVirtualTransactionSize(*tx);
     Amount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
 
     std::string err_string;
     AssertLockNotHeld(cs_main);
     NodeContext &node = EnsureNodeContext(request.context);
     const TransactionError err = BroadcastTransaction(
         node, config, tx, err_string, max_raw_tx_fee, /*relay*/ true,
         /*wait_callback*/ true);
     if (err != TransactionError::OK) {
         throw JSONRPCTransactionError(err, err_string);
     }
 
     return tx->GetHash().GetHex();
 }
 
 static UniValue testmempoolaccept(const Config &config,
                                   const JSONRPCRequest &request) {
     RPCHelpMan{
         "testmempoolaccept",
         "Returns result of mempool acceptance tests indicating if raw"
         " transaction (serialized, hex-encoded) would be accepted"
         " by mempool.\n"
         "\nThis checks if the transaction violates the consensus or policy "
         "rules.\n"
         "\nSee sendrawtransaction call.\n",
         {
             {
                 "rawtxs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "An array of hex strings of raw transactions.\n"
                 "                             Length must be one for now.",
                 {
                     {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED,
                      ""},
                 },
             },
             {"maxfeerate", RPCArg::Type::AMOUNT,
              /* default */
              FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()),
              "Reject transactions whose fee rate is higher than the specified "
              "value, expressed in " +
                  CURRENCY_UNIT + "/kB\n"},
         },
         RPCResult{RPCResult::Type::ARR,
                   "",
                   "The result of the mempool acceptance test for each raw "
                   "transaction in the input array.\n"
                   "Length is exactly one for now.",
                   {
                       {RPCResult::Type::OBJ,
                        "",
                        "",
                        {
                            {RPCResult::Type::STR_HEX, "txid",
                             "The transaction hash in hex"},
                            {RPCResult::Type::BOOL, "allowed",
                             "If the mempool allows this tx to be inserted"},
                            {RPCResult::Type::STR, "reject-reason",
                             "Rejection string (only present when 'allowed' is "
                             "false)"},
                        }},
                   }},
         RPCExamples{
             "\nCreate a transaction\n" +
             HelpExampleCli(
                 "createrawtransaction",
                 "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" "
                 "\"{\\\"myaddress\\\":0.01}\"") +
             "Sign the transaction, and get back the hex\n" +
             HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
             "\nTest acceptance of the transaction (signed hex)\n" +
             HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") +
             "\nAs a JSON-RPC call\n" +
             HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {
                                      UniValue::VARR,
                                      // NUM or BOOL, checked later
                                      UniValueType(),
                                  });
 
     if (request.params[0].get_array().size() != 1) {
         throw JSONRPCError(
             RPC_INVALID_PARAMETER,
             "Array must contain exactly one raw transaction for now");
     }
 
     CMutableTransaction mtx;
     if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
     }
     CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
     const TxId &txid = tx->GetId();
 
     CFeeRate max_raw_tx_fee_rate = DEFAULT_MAX_RAW_TX_FEE_RATE;
     // TODO: temporary migration code for old clients. Remove in v0.22
     if (request.params[1].isBool()) {
         throw JSONRPCError(RPC_INVALID_PARAMETER,
                            "Second argument must be numeric (maxfeerate) and "
                            "no longer supports a boolean. To allow a "
                            "transaction with high fees, set maxfeerate to 0.");
     } else if (!request.params[1].isNull()) {
         max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1]));
     }
 
     CTxMemPool &mempool = EnsureMemPool(request.context);
     int64_t virtual_size = GetVirtualTransactionSize(*tx);
     Amount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
 
     UniValue result(UniValue::VARR);
     UniValue result_0(UniValue::VOBJ);
     result_0.pushKV("txid", txid.GetHex());
 
     TxValidationState state;
     bool test_accept_res;
     {
         LOCK(cs_main);
         test_accept_res = AcceptToMemoryPool(
             config, mempool, state, std::move(tx), false /* bypass_limits */,
             max_raw_tx_fee, true /* test_accept */);
     }
     result_0.pushKV("allowed", test_accept_res);
     if (!test_accept_res) {
         if (state.IsInvalid()) {
             if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
                 result_0.pushKV("reject-reason", "missing-inputs");
             } else {
                 result_0.pushKV("reject-reason",
-                                strprintf("%i: %s", state.GetRejectCode(),
-                                          state.GetRejectReason()));
+                                strprintf("%s", state.GetRejectReason()));
             }
         } else {
             result_0.pushKV("reject-reason", state.GetRejectReason());
         }
     }
 
     result.push_back(std::move(result_0));
     return result;
 }
 
 static std::string WriteHDKeypath(std::vector<uint32_t> &keypath) {
     std::string keypath_str = "m";
     for (uint32_t num : keypath) {
         keypath_str += "/";
         bool hardened = false;
         if (num & 0x80000000) {
             hardened = true;
             num &= ~0x80000000;
         }
 
         keypath_str += std::to_string(num);
         if (hardened) {
             keypath_str += "'";
         }
     }
     return keypath_str;
 }
 
 static UniValue decodepsbt(const Config &config,
                            const JSONRPCRequest &request) {
     RPCHelpMan{
         "decodepsbt",
         "Return a JSON object representing the serialized, base64-encoded "
         "partially signed Bitcoin transaction.\n",
         {
             {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO,
              "The PSBT base64 string"},
         },
         RPCResult{
             RPCResult::Type::OBJ,
             "",
             "",
             {
                 {RPCResult::Type::OBJ,
                  "tx",
                  "The decoded network-serialized unsigned transaction.",
                  {
                      {RPCResult::Type::ELISION, "",
                       "The layout is the same as the output of "
                       "decoderawtransaction."},
                  }},
                 {RPCResult::Type::OBJ_DYN,
                  "unknown",
                  "The unknown global fields",
                  {
                      {RPCResult::Type::STR_HEX, "key",
                       "(key-value pair) An unknown key-value pair"},
                  }},
                 {RPCResult::Type::ARR,
                  "inputs",
                  "",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::OBJ,
                            "utxo",
                            /* optional */ true,
                            "Transaction output for UTXOs",
                            {
                                {RPCResult::Type::NUM, "amount",
                                 "The value in " + CURRENCY_UNIT},
                                {RPCResult::Type::OBJ,
                                 "scriptPubKey",
                                 "",
                                 {
                                     {RPCResult::Type::STR, "asm", "The asm"},
                                     {RPCResult::Type::STR_HEX, "hex",
                                      "The hex"},
                                     {RPCResult::Type::STR, "type",
                                      "The type, eg 'pubkeyhash'"},
                                     {RPCResult::Type::STR, "address",
                                      " Bitcoin address if there is one"},
                                 }},
                            }},
                           {RPCResult::Type::OBJ_DYN,
                            "partial_signatures",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::STR, "pubkey",
                                 "The public key and signature that corresponds "
                                 "to it."},
                            }},
                           {RPCResult::Type::STR, "sighash", /* optional */ true,
                            "The sighash type to be used"},
                           {RPCResult::Type::OBJ,
                            "redeem_script",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::STR, "asm", "The asm"},
                                {RPCResult::Type::STR_HEX, "hex", "The hex"},
                                {RPCResult::Type::STR, "type",
                                 "The type, eg 'pubkeyhash'"},
                            }},
                           {RPCResult::Type::ARR,
                            "bip32_derivs",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::OBJ,
                                 "pubkey",
                                 /* optional */ true,
                                 "The public key with the derivation path as "
                                 "the value.",
                                 {
                                     {RPCResult::Type::STR, "master_fingerprint",
                                      "The fingerprint of the master key"},
                                     {RPCResult::Type::STR, "path", "The path"},
                                 }},
                            }},
                           {RPCResult::Type::OBJ,
                            "final_scriptsig",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::STR, "asm", "The asm"},
                                {RPCResult::Type::STR, "hex", "The hex"},
                            }},
                           {RPCResult::Type::OBJ_DYN,
                            "unknown",
                            "The unknown global fields",
                            {
                                {RPCResult::Type::STR_HEX, "key",
                                 "(key-value pair) An unknown key-value pair"},
                            }},
                       }},
                  }},
                 {RPCResult::Type::ARR,
                  "outputs",
                  "",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::OBJ,
                            "redeem_script",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::STR, "asm", "The asm"},
                                {RPCResult::Type::STR_HEX, "hex", "The hex"},
                                {RPCResult::Type::STR, "type",
                                 "The type, eg 'pubkeyhash'"},
                            }},
                           {RPCResult::Type::ARR,
                            "bip32_derivs",
                            /* optional */ true,
                            "",
                            {
                                {RPCResult::Type::OBJ,
                                 "",
                                 "",
                                 {
                                     {RPCResult::Type::STR, "pubkey",
                                      "The public key this path corresponds to"},
                                     {RPCResult::Type::STR, "master_fingerprint",
                                      "The fingerprint of the master key"},
                                     {RPCResult::Type::STR, "path", "The path"},
                                 }},
                            }},
                           {RPCResult::Type::OBJ_DYN,
                            "unknown",
                            "The unknown global fields",
                            {
                                {RPCResult::Type::STR_HEX, "key",
                                 "(key-value pair) An unknown key-value pair"},
                            }},
                       }},
                  }},
                 {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true,
                  "The transaction fee paid if all UTXOs slots in the PSBT have "
                  "been filled."},
             }},
         RPCExamples{HelpExampleCli("decodepsbt", "\"psbt\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VSTR});
 
     // Unserialize the transactions
     PartiallySignedTransaction psbtx;
     std::string error;
     if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                            strprintf("TX decode failed %s", error));
     }
 
     UniValue result(UniValue::VOBJ);
 
     // Add the decoded tx
     UniValue tx_univ(UniValue::VOBJ);
     TxToUniv(CTransaction(*psbtx.tx), uint256(), tx_univ, false);
     result.pushKV("tx", tx_univ);
 
     // Unknown data
     if (psbtx.unknown.size() > 0) {
         UniValue unknowns(UniValue::VOBJ);
         for (auto entry : psbtx.unknown) {
             unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
         }
         result.pushKV("unknown", unknowns);
     }
 
     // inputs
     Amount total_in = Amount::zero();
     bool have_all_utxos = true;
     UniValue inputs(UniValue::VARR);
     for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
         const PSBTInput &input = psbtx.inputs[i];
         UniValue in(UniValue::VOBJ);
         // UTXOs
         if (!input.utxo.IsNull()) {
             const CTxOut &txout = input.utxo;
 
             UniValue out(UniValue::VOBJ);
 
             out.pushKV("amount", ValueFromAmount(txout.nValue));
             if (MoneyRange(txout.nValue) &&
                 MoneyRange(total_in + txout.nValue)) {
                 total_in += txout.nValue;
             } else {
                 // Hack to just not show fee later
                 have_all_utxos = false;
             }
 
             UniValue o(UniValue::VOBJ);
             ScriptToUniv(txout.scriptPubKey, o, true);
             out.pushKV("scriptPubKey", o);
             in.pushKV("utxo", out);
         } else {
             have_all_utxos = false;
         }
 
         // Partial sigs
         if (!input.partial_sigs.empty()) {
             UniValue partial_sigs(UniValue::VOBJ);
             for (const auto &sig : input.partial_sigs) {
                 partial_sigs.pushKV(HexStr(sig.second.first),
                                     HexStr(sig.second.second));
             }
             in.pushKV("partial_signatures", partial_sigs);
         }
 
         // Sighash
         uint8_t sighashbyte = input.sighash_type.getRawSigHashType() & 0xff;
         if (sighashbyte > 0) {
             in.pushKV("sighash", SighashToStr(sighashbyte));
         }
 
         // Redeem script
         if (!input.redeem_script.empty()) {
             UniValue r(UniValue::VOBJ);
             ScriptToUniv(input.redeem_script, r, false);
             in.pushKV("redeem_script", r);
         }
 
         // keypaths
         if (!input.hd_keypaths.empty()) {
             UniValue keypaths(UniValue::VARR);
             for (auto entry : input.hd_keypaths) {
                 UniValue keypath(UniValue::VOBJ);
                 keypath.pushKV("pubkey", HexStr(entry.first));
 
                 keypath.pushKV(
                     "master_fingerprint",
                     strprintf("%08x", ReadBE32(entry.second.fingerprint)));
                 keypath.pushKV("path", WriteHDKeypath(entry.second.path));
                 keypaths.push_back(keypath);
             }
             in.pushKV("bip32_derivs", keypaths);
         }
 
         // Final scriptSig
         if (!input.final_script_sig.empty()) {
             UniValue scriptsig(UniValue::VOBJ);
             scriptsig.pushKV("asm",
                              ScriptToAsmStr(input.final_script_sig, true));
             scriptsig.pushKV("hex", HexStr(input.final_script_sig));
             in.pushKV("final_scriptSig", scriptsig);
         }
 
         // Unknown data
         if (input.unknown.size() > 0) {
             UniValue unknowns(UniValue::VOBJ);
             for (auto entry : input.unknown) {
                 unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
             }
             in.pushKV("unknown", unknowns);
         }
 
         inputs.push_back(in);
     }
     result.pushKV("inputs", inputs);
 
     // outputs
     Amount output_value = Amount::zero();
     UniValue outputs(UniValue::VARR);
     for (size_t i = 0; i < psbtx.outputs.size(); ++i) {
         const PSBTOutput &output = psbtx.outputs[i];
         UniValue out(UniValue::VOBJ);
         // Redeem script
         if (!output.redeem_script.empty()) {
             UniValue r(UniValue::VOBJ);
             ScriptToUniv(output.redeem_script, r, false);
             out.pushKV("redeem_script", r);
         }
 
         // keypaths
         if (!output.hd_keypaths.empty()) {
             UniValue keypaths(UniValue::VARR);
             for (auto entry : output.hd_keypaths) {
                 UniValue keypath(UniValue::VOBJ);
                 keypath.pushKV("pubkey", HexStr(entry.first));
                 keypath.pushKV(
                     "master_fingerprint",
                     strprintf("%08x", ReadBE32(entry.second.fingerprint)));
                 keypath.pushKV("path", WriteHDKeypath(entry.second.path));
                 keypaths.push_back(keypath);
             }
             out.pushKV("bip32_derivs", keypaths);
         }
 
         // Unknown data
         if (output.unknown.size() > 0) {
             UniValue unknowns(UniValue::VOBJ);
             for (auto entry : output.unknown) {
                 unknowns.pushKV(HexStr(entry.first), HexStr(entry.second));
             }
             out.pushKV("unknown", unknowns);
         }
 
         outputs.push_back(out);
 
         // Fee calculation
         if (MoneyRange(psbtx.tx->vout[i].nValue) &&
             MoneyRange(output_value + psbtx.tx->vout[i].nValue)) {
             output_value += psbtx.tx->vout[i].nValue;
         } else {
             // Hack to just not show fee later
             have_all_utxos = false;
         }
     }
     result.pushKV("outputs", outputs);
     if (have_all_utxos) {
         result.pushKV("fee", ValueFromAmount(total_in - output_value));
     }
 
     return result;
 }
 
 static UniValue combinepsbt(const Config &config,
                             const JSONRPCRequest &request) {
     RPCHelpMan{
         "combinepsbt",
         "Combine multiple partially signed Bitcoin transactions into one "
         "transaction.\n"
         "Implements the Combiner role.\n",
         {
             {
                 "txs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of base64 strings of partially signed "
                 "transactions",
                 {
                     {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED,
                      "A base64 string of a PSBT"},
                 },
             },
         },
         RPCResult{RPCResult::Type::STR, "",
                   "The base64-encoded partially signed transaction"},
         RPCExamples{HelpExampleCli(
             "combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VARR}, true);
 
     // Unserialize the transactions
     std::vector<PartiallySignedTransaction> psbtxs;
     UniValue txs = request.params[0].get_array();
     if (txs.empty()) {
         throw JSONRPCError(RPC_INVALID_PARAMETER,
                            "Parameter 'txs' cannot be empty");
     }
     for (size_t i = 0; i < txs.size(); ++i) {
         PartiallySignedTransaction psbtx;
         std::string error;
         if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
             throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                strprintf("TX decode failed %s", error));
         }
         psbtxs.push_back(psbtx);
     }
 
     PartiallySignedTransaction merged_psbt;
     const TransactionError error = CombinePSBTs(merged_psbt, psbtxs);
     if (error != TransactionError::OK) {
         throw JSONRPCTransactionError(error);
     }
 
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << merged_psbt;
     return EncodeBase64((uint8_t *)ssTx.data(), ssTx.size());
 }
 
 static UniValue finalizepsbt(const Config &config,
                              const JSONRPCRequest &request) {
     RPCHelpMan{
         "finalizepsbt",
         "Finalize the inputs of a PSBT. If the transaction is fully signed, it "
         "will produce a\n"
         "network serialized transaction which can be broadcast with "
         "sendrawtransaction. Otherwise a PSBT will be\n"
         "created which has the final_scriptSigfields filled for inputs that "
         "are complete.\n"
         "Implements the Finalizer and Extractor roles.\n",
         {
             {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO,
              "A base64 string of a PSBT"},
             {"extract", RPCArg::Type::BOOL, /* default */ "true",
              "If true and the transaction is complete,\n"
              "                             extract and return the complete "
              "transaction in normal network serialization instead of the "
              "PSBT."},
         },
         RPCResult{RPCResult::Type::OBJ,
                   "",
                   "",
                   {
                       {RPCResult::Type::STR, "psbt",
                        "The base64-encoded partially signed transaction if not "
                        "extracted"},
                       {RPCResult::Type::STR_HEX, "hex",
                        "The hex-encoded network transaction if extracted"},
                       {RPCResult::Type::BOOL, "complete",
                        "If the transaction has a complete set of signatures"},
                   }},
         RPCExamples{HelpExampleCli("finalizepsbt", "\"psbt\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
 
     // Unserialize the transactions
     PartiallySignedTransaction psbtx;
     std::string error;
     if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                            strprintf("TX decode failed %s", error));
     }
 
     bool extract = request.params[1].isNull() || (!request.params[1].isNull() &&
                                                   request.params[1].get_bool());
 
     CMutableTransaction mtx;
     bool complete = FinalizeAndExtractPSBT(psbtx, mtx);
 
     UniValue result(UniValue::VOBJ);
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     std::string result_str;
 
     if (complete && extract) {
         ssTx << mtx;
         result_str = HexStr(ssTx.str());
         result.pushKV("hex", result_str);
     } else {
         ssTx << psbtx;
         result_str = EncodeBase64(ssTx.str());
         result.pushKV("psbt", result_str);
     }
     result.pushKV("complete", complete);
 
     return result;
 }
 
 static UniValue createpsbt(const Config &config,
                            const JSONRPCRequest &request) {
     RPCHelpMan{
         "createpsbt",
         "Creates a transaction in the Partially Signed Transaction format.\n"
         "Implements the Creator role.\n",
         {
             {
                 "inputs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "A json array of json objects",
                 {
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"txid", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO, "The transaction id"},
                             {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO,
                              "The output number"},
                             {"sequence", RPCArg::Type::NUM, /* default */
                              "depends on the value of the 'locktime' argument",
                              "The sequence number"},
                         },
                     },
                 },
             },
             {
                 "outputs",
                 RPCArg::Type::ARR,
                 RPCArg::Optional::NO,
                 "a json array with outputs (key-value pairs), where none of "
                 "the keys are duplicated.\n"
                 "That is, each address can only appear once and there can only "
                 "be one 'data' object.\n"
                 "For compatibility reasons, a dictionary, which holds the "
                 "key-value pairs directly, is also\n"
                 "                             accepted as second parameter.",
                 {
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"address", RPCArg::Type::AMOUNT,
                              RPCArg::Optional::NO,
                              "A key-value pair. The key (string) is the "
                              "bitcoin address, the value (float or string) is "
                              "the amount in " +
                                  CURRENCY_UNIT},
                         },
                     },
                     {
                         "",
                         RPCArg::Type::OBJ,
                         RPCArg::Optional::OMITTED,
                         "",
                         {
                             {"data", RPCArg::Type::STR_HEX,
                              RPCArg::Optional::NO,
                              "A key-value pair. The key must be \"data\", the "
                              "value is hex-encoded data"},
                         },
                     },
                 },
             },
             {"locktime", RPCArg::Type::NUM, /* default */ "0",
              "Raw locktime. Non-0 value also locktime-activates inputs"},
         },
         RPCResult{RPCResult::Type::STR, "",
                   "The resulting raw transaction (base64-encoded string)"},
         RPCExamples{HelpExampleCli(
             "createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]"
                           "\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params,
                  {
                      UniValue::VARR,
                      UniValueType(), // ARR or OBJ, checked later
                      UniValue::VNUM,
                  },
                  true);
 
     CMutableTransaction rawTx =
         ConstructTransaction(config.GetChainParams(), request.params[0],
                              request.params[1], request.params[2]);
 
     // Make a blank psbt
     PartiallySignedTransaction psbtx;
     psbtx.tx = rawTx;
     for (size_t i = 0; i < rawTx.vin.size(); ++i) {
         psbtx.inputs.push_back(PSBTInput());
     }
     for (size_t i = 0; i < rawTx.vout.size(); ++i) {
         psbtx.outputs.push_back(PSBTOutput());
     }
 
     // Serialize the PSBT
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << psbtx;
 
     return EncodeBase64((uint8_t *)ssTx.data(), ssTx.size());
 }
 
 static UniValue converttopsbt(const Config &config,
                               const JSONRPCRequest &request) {
     RPCHelpMan{
         "converttopsbt",
         "Converts a network serialized transaction to a PSBT. "
         "This should be used only with createrawtransaction and "
         "fundrawtransaction\n"
         "createpsbt and walletcreatefundedpsbt should be used for new "
         "applications.\n",
         {
             {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
              "The hex string of a raw transaction"},
             {"permitsigdata", RPCArg::Type::BOOL, /* default */ "false",
              "If true, any signatures in the input will be discarded and "
              "conversion.\n"
              "                              will continue. If false, RPC will "
              "fail if any signatures are present."},
         },
         RPCResult{RPCResult::Type::STR, "",
                   "The resulting raw transaction (base64-encoded string)"},
         RPCExamples{
             "\nCreate a transaction\n" +
             HelpExampleCli("createrawtransaction",
                            "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]"
                            "\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") +
             "\nConvert the transaction to a PSBT\n" +
             HelpExampleCli("converttopsbt", "\"rawtransaction\"")},
     }
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
 
     // parse hex string from parameter
     CMutableTransaction tx;
     bool permitsigdata =
         request.params[1].isNull() ? false : request.params[1].get_bool();
     if (!DecodeHexTx(tx, request.params[0].get_str())) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
     }
 
     // Remove all scriptSigs from inputs
     for (CTxIn &input : tx.vin) {
         if (!input.scriptSig.empty() && !permitsigdata) {
             throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                "Inputs must not have scriptSigs");
         }
         input.scriptSig.clear();
     }
 
     // Make a blank psbt
     PartiallySignedTransaction psbtx;
     psbtx.tx = tx;
     for (size_t i = 0; i < tx.vin.size(); ++i) {
         psbtx.inputs.push_back(PSBTInput());
     }
     for (size_t i = 0; i < tx.vout.size(); ++i) {
         psbtx.outputs.push_back(PSBTOutput());
     }
 
     // Serialize the PSBT
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << psbtx;
 
     return EncodeBase64((uint8_t *)ssTx.data(), ssTx.size());
 }
 
 UniValue utxoupdatepsbt(const Config &config, const JSONRPCRequest &request) {
     RPCHelpMan{
         "utxoupdatepsbt",
         "Updates all inputs and outputs in a PSBT with data from output "
         "descriptors, the UTXO set or the mempool.\n",
         {
             {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO,
              "A base64 string of a PSBT"},
             {"descriptors",
              RPCArg::Type::ARR,
              RPCArg::Optional::OMITTED_NAMED_ARG,
              "An array of either strings or objects",
              {
                  {"", RPCArg::Type::STR, RPCArg::Optional::OMITTED,
                   "An output descriptor"},
                  {"",
                   RPCArg::Type::OBJ,
                   RPCArg::Optional::OMITTED,
                   "An object with an output descriptor and extra information",
                   {
                       {"desc", RPCArg::Type::STR, RPCArg::Optional::NO,
                        "An output descriptor"},
                       {"range", RPCArg::Type::RANGE, "1000",
                        "Up to what index HD chains should be explored (either "
                        "end or [begin,end])"},
                   }},
              }},
         },
         RPCResult{RPCResult::Type::STR, "",
                   "The base64-encoded partially signed transaction with inputs "
                   "updated"},
         RPCExamples{HelpExampleCli("utxoupdatepsbt", "\"psbt\"")}}
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true);
 
     // Unserialize the transactions
     PartiallySignedTransaction psbtx;
     std::string error;
     if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                            strprintf("TX decode failed %s", error));
     }
 
     // Parse descriptors, if any.
     FlatSigningProvider provider;
     if (!request.params[1].isNull()) {
         auto descs = request.params[1].get_array();
         for (size_t i = 0; i < descs.size(); ++i) {
             EvalDescriptorStringOrObject(descs[i], provider);
         }
     }
     // We don't actually need private keys further on; hide them as a
     // precaution.
     HidingSigningProvider public_provider(&provider, /* nosign */ true,
                                           /* nobip32derivs */ false);
 
     // Fetch previous transactions (inputs):
     CCoinsView viewDummy;
     CCoinsViewCache view(&viewDummy);
     {
         const CTxMemPool &mempool = EnsureMemPool(request.context);
         LOCK2(cs_main, mempool.cs);
         CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
         CCoinsViewMemPool viewMempool(&viewChain, mempool);
         // temporarily switch cache backend to db+mempool view
         view.SetBackend(viewMempool);
 
         for (const CTxIn &txin : psbtx.tx->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);
     }
 
     // Fill the inputs
     for (size_t i = 0; i < psbtx.tx->vin.size(); ++i) {
         PSBTInput &input = psbtx.inputs.at(i);
 
         if (!input.utxo.IsNull()) {
             continue;
         }
 
         // Update script/keypath information using descriptor data.
         // Note that SignPSBTInput does a lot more than just constructing ECDSA
         // signatures we don't actually care about those here, in fact.
         SignPSBTInput(public_provider, psbtx, i,
                       /* sighash_type */ SigHashType().withForkId());
     }
 
     // Update script/keypath information using descriptor data.
     for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
         UpdatePSBTOutput(public_provider, psbtx, i);
     }
 
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << psbtx;
     return EncodeBase64((uint8_t *)ssTx.data(), ssTx.size());
 }
 
 UniValue joinpsbts(const Config &config, const JSONRPCRequest &request) {
     RPCHelpMan{
         "joinpsbts",
         "Joins multiple distinct PSBTs with different inputs and outputs "
         "into one PSBT with inputs and outputs from all of the PSBTs\n"
         "No input in any of the PSBTs can be in more than one of the PSBTs.\n",
         {{"txs",
           RPCArg::Type::ARR,
           RPCArg::Optional::NO,
           "A json array of base64 strings of partially signed transactions",
           {{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO,
             "A base64 string of a PSBT"}}}},
         RPCResult{RPCResult::Type::STR, "",
                   "The base64-encoded partially signed transaction"},
         RPCExamples{HelpExampleCli("joinpsbts", "\"psbt\"")}}
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VARR}, true);
 
     // Unserialize the transactions
     std::vector<PartiallySignedTransaction> psbtxs;
     UniValue txs = request.params[0].get_array();
 
     if (txs.size() <= 1) {
         throw JSONRPCError(RPC_INVALID_PARAMETER,
                            "At least two PSBTs are required to join PSBTs.");
     }
 
     int32_t best_version = 1;
     uint32_t best_locktime = 0xffffffff;
     for (size_t i = 0; i < txs.size(); ++i) {
         PartiallySignedTransaction psbtx;
         std::string error;
         if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
             throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                                strprintf("TX decode failed %s", error));
         }
         psbtxs.push_back(psbtx);
         // Choose the highest version number
         if (psbtx.tx->nVersion > best_version) {
             best_version = psbtx.tx->nVersion;
         }
         // Choose the lowest lock time
         if (psbtx.tx->nLockTime < best_locktime) {
             best_locktime = psbtx.tx->nLockTime;
         }
     }
 
     // Create a blank psbt where everything will be added
     PartiallySignedTransaction merged_psbt;
     merged_psbt.tx = CMutableTransaction();
     merged_psbt.tx->nVersion = best_version;
     merged_psbt.tx->nLockTime = best_locktime;
 
     // Merge
     for (auto &psbt : psbtxs) {
         for (size_t i = 0; i < psbt.tx->vin.size(); ++i) {
             if (!merged_psbt.AddInput(psbt.tx->vin[i], psbt.inputs[i])) {
                 throw JSONRPCError(
                     RPC_INVALID_PARAMETER,
                     strprintf(
                         "Input %s:%d exists in multiple PSBTs",
                         psbt.tx->vin[i].prevout.GetTxId().ToString().c_str(),
                         psbt.tx->vin[i].prevout.GetN()));
             }
         }
         for (size_t i = 0; i < psbt.tx->vout.size(); ++i) {
             merged_psbt.AddOutput(psbt.tx->vout[i], psbt.outputs[i]);
         }
         merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
     }
 
     // Generate list of shuffled indices for shuffling inputs and outputs of the
     // merged PSBT
     std::vector<int> input_indices(merged_psbt.inputs.size());
     std::iota(input_indices.begin(), input_indices.end(), 0);
     std::vector<int> output_indices(merged_psbt.outputs.size());
     std::iota(output_indices.begin(), output_indices.end(), 0);
 
     // Shuffle input and output indicies lists
     Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
     Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
 
     PartiallySignedTransaction shuffled_psbt;
     shuffled_psbt.tx = CMutableTransaction();
     shuffled_psbt.tx->nVersion = merged_psbt.tx->nVersion;
     shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;
     for (int i : input_indices) {
         shuffled_psbt.AddInput(merged_psbt.tx->vin[i], merged_psbt.inputs[i]);
     }
     for (int i : output_indices) {
         shuffled_psbt.AddOutput(merged_psbt.tx->vout[i],
                                 merged_psbt.outputs[i]);
     }
     shuffled_psbt.unknown.insert(merged_psbt.unknown.begin(),
                                  merged_psbt.unknown.end());
 
     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     ssTx << shuffled_psbt;
     return EncodeBase64((uint8_t *)ssTx.data(), ssTx.size());
 }
 
 UniValue analyzepsbt(const Config &config, const JSONRPCRequest &request) {
     RPCHelpMan{
         "analyzepsbt",
         "Analyzes and provides information about the current status of a "
         "PSBT and its inputs\n",
         {{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO,
           "A base64 string of a PSBT"}},
         RPCResult{
             RPCResult::Type::OBJ,
             "",
             "",
             {
                 {RPCResult::Type::ARR,
                  "inputs",
                  "",
                  {
                      {RPCResult::Type::OBJ,
                       "",
                       "",
                       {
                           {RPCResult::Type::BOOL, "has_utxo",
                            "Whether a UTXO is provided"},
                           {RPCResult::Type::BOOL, "is_final",
                            "Whether the input is finalized"},
                           {RPCResult::Type::OBJ,
                            "missing",
                            /* optional */ true,
                            "Things that are missing that are required to "
                            "complete this input",
                            {
                                {RPCResult::Type::ARR,
                                 "pubkeys",
                                 /* optional */ true,
                                 "",
                                 {
                                     {RPCResult::Type::STR_HEX, "keyid",
                                      "Public key ID, hash160 of the public "
                                      "key, of a public key whose BIP 32 "
                                      "derivation path is missing"},
                                 }},
                                {RPCResult::Type::ARR,
                                 "signatures",
                                 /* optional */ true,
                                 "",
                                 {
                                     {RPCResult::Type::STR_HEX, "keyid",
                                      "Public key ID, hash160 of the public "
                                      "key, of a public key whose signature is "
                                      "missing"},
                                 }},
                                {RPCResult::Type::STR_HEX, "redeemscript",
                                 /* optional */ true,
                                 "Hash160 of the redeemScript that is missing"},
                            }},
                           {RPCResult::Type::STR, "next", /* optional */ true,
                            "Role of the next person that this input needs to "
                            "go to"},
                       }},
                  }},
                 {RPCResult::Type::NUM, "estimated_vsize", /* optional */ true,
                  "Estimated vsize of the final signed transaction"},
                 {RPCResult::Type::STR_AMOUNT, "estimated_feerate",
                  /* optional */ true,
                  "Estimated feerate of the final signed transaction in " +
                      CURRENCY_UNIT +
                      "/kB. Shown only if all UTXO slots in the PSBT have been "
                      "filled"},
                 {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true,
                  "The transaction fee paid. Shown only if all UTXO slots in "
                  "the PSBT have been filled"},
                 {RPCResult::Type::STR, "next",
                  "Role of the next person that this psbt needs to go to"},
                 {RPCResult::Type::STR, "error",
                  "Error message if there is one"},
             }},
         RPCExamples{HelpExampleCli("analyzepsbt", "\"psbt\"")}}
         .Check(request);
 
     RPCTypeCheck(request.params, {UniValue::VSTR});
 
     // Unserialize the transaction
     PartiallySignedTransaction psbtx;
     std::string error;
     if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
         throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
                            strprintf("TX decode failed %s", error));
     }
 
     PSBTAnalysis psbta = AnalyzePSBT(psbtx);
 
     UniValue result(UniValue::VOBJ);
     UniValue inputs_result(UniValue::VARR);
     for (const auto &input : psbta.inputs) {
         UniValue input_univ(UniValue::VOBJ);
         UniValue missing(UniValue::VOBJ);
 
         input_univ.pushKV("has_utxo", input.has_utxo);
         input_univ.pushKV("is_final", input.is_final);
         input_univ.pushKV("next", PSBTRoleName(input.next));
 
         if (!input.missing_pubkeys.empty()) {
             UniValue missing_pubkeys_univ(UniValue::VARR);
             for (const CKeyID &pubkey : input.missing_pubkeys) {
                 missing_pubkeys_univ.push_back(HexStr(pubkey));
             }
             missing.pushKV("pubkeys", missing_pubkeys_univ);
         }
         if (!input.missing_redeem_script.IsNull()) {
             missing.pushKV("redeemscript", HexStr(input.missing_redeem_script));
         }
         if (!input.missing_sigs.empty()) {
             UniValue missing_sigs_univ(UniValue::VARR);
             for (const CKeyID &pubkey : input.missing_sigs) {
                 missing_sigs_univ.push_back(HexStr(pubkey));
             }
             missing.pushKV("signatures", missing_sigs_univ);
         }
         if (!missing.getKeys().empty()) {
             input_univ.pushKV("missing", missing);
         }
         inputs_result.push_back(input_univ);
     }
     if (!inputs_result.empty()) {
         result.pushKV("inputs", inputs_result);
     }
     if (psbta.estimated_vsize != nullopt) {
         result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
     }
     if (psbta.estimated_feerate != nullopt) {
         result.pushKV("estimated_feerate",
                       ValueFromAmount(psbta.estimated_feerate->GetFeePerK()));
     }
     if (psbta.fee != nullopt) {
         result.pushKV("fee", ValueFromAmount(*psbta.fee));
     }
     result.pushKV("next", PSBTRoleName(psbta.next));
     if (!psbta.error.empty()) {
         result.pushKV("error", psbta.error);
     }
 
     return result;
 }
 
 // clang-format off
 static const CRPCCommand commands[] = {
     //  category            name                         actor (function)           argNames
     //  ------------------- ------------------------     ----------------------     ----------
     { "rawtransactions",    "getrawtransaction",         getrawtransaction,         {"txid","verbose","blockhash"} },
     { "rawtransactions",    "createrawtransaction",      createrawtransaction,      {"inputs","outputs","locktime"} },
     { "rawtransactions",    "decoderawtransaction",      decoderawtransaction,      {"hexstring"} },
     { "rawtransactions",    "decodescript",              decodescript,              {"hexstring"} },
     { "rawtransactions",    "sendrawtransaction",        sendrawtransaction,        {"hexstring","allowhighfees|maxfeerate"} },
     { "rawtransactions",    "combinerawtransaction",     combinerawtransaction,     {"txs"} },
     { "rawtransactions",    "signrawtransactionwithkey", signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
     { "rawtransactions",    "testmempoolaccept",         testmempoolaccept,         {"rawtxs","allowhighfees|maxfeerate"} },
     { "rawtransactions",    "decodepsbt",                decodepsbt,                {"psbt"} },
     { "rawtransactions",    "combinepsbt",               combinepsbt,               {"txs"} },
     { "rawtransactions",    "finalizepsbt",              finalizepsbt,              {"psbt", "extract"} },
     { "rawtransactions",    "createpsbt",                createpsbt,                {"inputs","outputs","locktime"} },
     { "rawtransactions",    "converttopsbt",             converttopsbt,             {"hexstring","permitsigdata"} },
     { "rawtransactions",    "utxoupdatepsbt",            utxoupdatepsbt,            {"psbt", "descriptors"} },
     { "rawtransactions",    "joinpsbts",                 joinpsbts,                 {"txs"} },
     { "rawtransactions",    "analyzepsbt",               analyzepsbt,               {"psbt"} },
     { "blockchain",         "gettxoutproof",             gettxoutproof,             {"txids", "blockhash"} },
     { "blockchain",         "verifytxoutproof",          verifytxoutproof,          {"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/src/util/validation.cpp b/src/util/validation.cpp
index fb45fece6..db6888333 100644
--- a/src/util/validation.cpp
+++ b/src/util/validation.cpp
@@ -1,24 +1,22 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2019 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 <util/validation.h>
 
 #include <consensus/validation.h>
 #include <tinyformat.h>
 
 std::string FormatStateMessage(const ValidationState &state) {
     if (state.IsValid()) {
         return "Valid";
     }
 
     const std::string debug_message = state.GetDebugMessage();
     if (!debug_message.empty()) {
-        return strprintf("%s, %s (code %i)", state.GetRejectReason(),
-                         debug_message, state.GetRejectCode());
+        return strprintf("%s, %s", state.GetRejectReason(), debug_message);
     }
 
-    return strprintf("%s (code %i)", state.GetRejectReason(),
-                     state.GetRejectCode());
+    return strprintf("%s", state.GetRejectReason());
 }
diff --git a/test/functional/abc-mempool-coherence-on-activations.py b/test/functional/abc-mempool-coherence-on-activations.py
index cb628cbcd..981df997a 100755
--- a/test/functional/abc-mempool-coherence-on-activations.py
+++ b/test/functional/abc-mempool-coherence-on-activations.py
@@ -1,378 +1,378 @@
 #!/usr/bin/env python3
 # Copyright (c) 2015-2016 The Bitcoin Core developers
 # Copyright (c) 2017 The Bitcoin developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 """
 This test checks the mempool coherence when changing validation rulesets,
 which happens on (de)activations of network upgrades (forks).
 
 We test the mempool coherence in 3 cases:
 1) on activations, pre-fork-only transactions are evicted from the mempool,
    while always-valid transactions remain.
 2) on deactivations, post-fork-only transactions (unconfirmed or once
    confirmed) are evicted from the mempool, while always-valid transactions
    are reincluded.
 3) on a reorg to a chain that deactivates and reactivates the fork,
    post-fork-only and always-valid transactions (unconfirmed and/or once
    confirmed on the shorter chain) are kept or reincluded in the mempool.
 """
 
 from test_framework.blocktools import (
     create_block,
     create_coinbase,
     create_tx_with_script,
     make_conform_to_ctor,
 )
 from test_framework.key import ECKey
 from test_framework.messages import (
     COIN,
     COutPoint,
     CTransaction,
     CTxIn,
     CTxOut,
     ToHex,
 )
 from test_framework.mininode import P2PDataStore
 from test_framework.script import (
     CScript,
     OP_CHECKSIG,
     OP_TRUE,
     SIGHASH_ALL,
     SIGHASH_FORKID,
     SignatureHashForkId,
 )
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal, assert_raises_rpc_error
 
 
 # ---Code specific to the activation used for this test---
 
 # It might change depending on the activation code currently existing in the
 # client software. We use the replay protection activation for this test.
 ACTIVATION_TIME = 2000000000
 EXTRA_ARG = "-replayprotectionactivationtime={}".format(ACTIVATION_TIME)
 
 # simulation starts before activation
 FIRST_BLOCK_TIME = ACTIVATION_TIME - 86400
 
 # Expected RPC error when trying to send an activation specific spend txn.
-RPC_EXPECTED_ERROR = "mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 16)"
+RPC_EXPECTED_ERROR = "mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)"
 
 
 def create_fund_and_activation_specific_spending_tx(spend, pre_fork_only):
     # Creates 2 transactions:
     # 1) txfund: create outputs to be used by txspend. Must be valid pre-fork.
     # 2) txspend: spending transaction that is specific to the activation
     #    being used and can be pre-fork-only or post-fork-only, depending on the
     #    function parameter.
 
     # This specific implementation uses the replay protection mechanism to
     # create transactions that are only valid before or after the fork.
 
     # Generate a key pair to test
     private_key = ECKey()
     private_key.generate()
     public_key = private_key.get_pubkey().get_bytes()
 
     # Fund transaction
     script = CScript([public_key, OP_CHECKSIG])
     txfund = create_tx_with_script(
         spend.tx, spend.n, b'', amount=50 * COIN, script_pub_key=script)
     txfund.rehash()
 
     # Activation specific spending tx
     txspend = CTransaction()
     txspend.vout.append(CTxOut(50 * COIN - 1000, CScript([OP_TRUE])))
     txspend.vin.append(CTxIn(COutPoint(txfund.sha256, 0), b''))
 
     # Sign the transaction
     # Use forkvalues that create pre-fork-only or post-fork-only
     # transactions.
     forkvalue = 0 if pre_fork_only else 0xffdead
     sighashtype = (forkvalue << 8) | SIGHASH_ALL | SIGHASH_FORKID
     sighash = SignatureHashForkId(
         script, txspend, 0, sighashtype, 50 * COIN)
     sig = private_key.sign_ecdsa(sighash) + \
         bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
     txspend.vin[0].scriptSig = CScript([sig])
     txspend.rehash()
 
     return txfund, txspend
 
 
 def create_fund_and_pre_fork_only_tx(spend):
     return create_fund_and_activation_specific_spending_tx(
         spend, pre_fork_only=True)
 
 
 def create_fund_and_post_fork_only_tx(spend):
     return create_fund_and_activation_specific_spending_tx(
         spend, pre_fork_only=False)
 
 
 # ---Mempool coherence on activations test---
 
 
 class PreviousSpendableOutput(object):
 
     def __init__(self, tx=CTransaction(), n=-1):
         self.tx = tx
         self.n = n
 
 
 class MempoolCoherenceOnActivationsTest(BitcoinTestFramework):
 
     def set_test_params(self):
         self.num_nodes = 1
         self.setup_clean_chain = True
         self.block_heights = {}
         self.tip = None
         self.blocks = {}
         self.extra_args = [['-whitelist=127.0.0.1',
                             EXTRA_ARG,
                             '-acceptnonstdtxn=1']]
 
     def next_block(self, number):
         if self.tip is None:
             base_block_hash = self.genesis_hash
             block_time = FIRST_BLOCK_TIME
         else:
             base_block_hash = self.tip.sha256
             block_time = self.tip.nTime + 1
         # First create the coinbase
         height = self.block_heights[base_block_hash] + 1
         coinbase = create_coinbase(height)
         coinbase.rehash()
         block = create_block(base_block_hash, coinbase, block_time)
 
         # Do PoW, which is cheap on regnet
         block.solve()
         self.tip = block
         self.block_heights[block.sha256] = height
         assert number not in self.blocks
         self.blocks[number] = block
         return block
 
     def run_test(self):
         node = self.nodes[0]
         node.add_p2p_connection(P2PDataStore())
         node.setmocktime(ACTIVATION_TIME)
 
         self.genesis_hash = int(node.getbestblockhash(), 16)
         self.block_heights[self.genesis_hash] = 0
         spendable_outputs = []
 
         # save the current tip so it can be spent by a later block
         def save_spendable_output():
             spendable_outputs.append(self.tip)
 
         # get an output that we previously marked as spendable
         def get_spendable_output():
             return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0)
 
         # move the tip back to a previous block
         def tip(number):
             self.tip = self.blocks[number]
 
         # adds transactions to the block and updates state
         def update_block(block_number, new_transactions):
             block = self.blocks[block_number]
             block.vtx.extend(new_transactions)
             old_sha256 = block.sha256
             make_conform_to_ctor(block)
             block.hashMerkleRoot = block.calc_merkle_root()
             block.solve()
             # Update the internal state just like in next_block
             self.tip = block
             if block.sha256 != old_sha256:
                 self.block_heights[
                     block.sha256] = self.block_heights[old_sha256]
                 del self.block_heights[old_sha256]
             self.blocks[block_number] = block
             return block
 
         # send a txn to the mempool and check it was accepted
         def send_transaction_to_mempool(tx):
             tx_id = node.sendrawtransaction(ToHex(tx))
             assert tx_id in node.getrawmempool()
 
         # checks the mempool has exactly the same txns as in the provided list
         def check_mempool_equal(txns):
             assert set(node.getrawmempool()) == set(tx.hash for tx in txns)
 
         # Create an always-valid chained transaction. It spends a
         # scriptPub=OP_TRUE coin into another. Returns the transaction and its
         # spendable output for further chaining.
         def create_always_valid_chained_tx(spend):
             tx = create_tx_with_script(
                 spend.tx, spend.n, b'', amount=spend.tx.vout[0].nValue - 1000, script_pub_key=CScript([OP_TRUE]))
             tx.rehash()
             return tx, PreviousSpendableOutput(tx, 0)
 
         # shorthand
         block = self.next_block
 
         # Create a new block
         block(0)
         save_spendable_output()
         node.p2p.send_blocks_and_test([self.tip], node)
 
         # Now we need that block to mature so we can spend the coinbase.
         maturity_blocks = []
         for i in range(110):
             block(5000 + i)
             maturity_blocks.append(self.tip)
             save_spendable_output()
         node.p2p.send_blocks_and_test(maturity_blocks, node)
 
         # collect spendable outputs now to avoid cluttering the code later on
         out = []
         for i in range(100):
             out.append(get_spendable_output())
 
         # Create 2 pre-fork-only txns (tx_pre0, tx_pre1). Fund txns are valid
         # pre-fork, so we can mine them right away.
         txfund0, tx_pre0 = create_fund_and_pre_fork_only_tx(out[0])
         txfund1, tx_pre1 = create_fund_and_pre_fork_only_tx(out[1])
 
         # Create 2 post-fork-only txns (tx_post0, tx_post1). Fund txns are
         # valid pre-fork, so we can mine them right away.
         txfund2, tx_post0 = create_fund_and_post_fork_only_tx(out[2])
         txfund3, tx_post1 = create_fund_and_post_fork_only_tx(out[3])
 
         # Create blocks to activate the fork. Mine all funding transactions.
         bfork = block(5555)
         bfork.nTime = ACTIVATION_TIME - 1
         update_block(5555, [txfund0, txfund1, txfund2, txfund3])
         node.p2p.send_blocks_and_test([self.tip], node)
 
         for i in range(5):
             node.p2p.send_blocks_and_test([block(5200 + i)], node)
 
         # Check we are just before the activation time
         assert_equal(
             node.getblockchaininfo()['mediantime'],
             ACTIVATION_TIME - 1)
 
         # We are just before the fork. Pre-fork-only and always-valid chained
         # txns (tx_chain0, tx_chain1) are valid, post-fork-only txns are
         # rejected.
         send_transaction_to_mempool(tx_pre0)
         send_transaction_to_mempool(tx_pre1)
         tx_chain0, last_chained_output = create_always_valid_chained_tx(out[4])
         tx_chain1, last_chained_output = create_always_valid_chained_tx(
             last_chained_output)
         send_transaction_to_mempool(tx_chain0)
         send_transaction_to_mempool(tx_chain1)
         assert_raises_rpc_error(-26, RPC_EXPECTED_ERROR,
                                 node.sendrawtransaction, ToHex(tx_post0))
         assert_raises_rpc_error(-26, RPC_EXPECTED_ERROR,
                                 node.sendrawtransaction, ToHex(tx_post1))
         check_mempool_equal([tx_chain0, tx_chain1, tx_pre0, tx_pre1])
 
         # Activate the fork. Mine the 1st always-valid chained txn and a
         # pre-fork-only txn.
         block(5556)
         update_block(5556, [tx_chain0, tx_pre0])
         node.p2p.send_blocks_and_test([self.tip], node)
         forkblockid = node.getbestblockhash()
 
         # Check we just activated the fork
         assert_equal(node.getblockheader(forkblockid)['mediantime'],
                      ACTIVATION_TIME)
 
         # Check mempool coherence when activating the fork. Pre-fork-only txns
         # were evicted from the mempool, while always-valid txns remain.
         # Evicted: tx_pre1
         check_mempool_equal([tx_chain1])
 
         # Post-fork-only and always-valid txns are accepted, pre-fork-only txn
         # are rejected.
         send_transaction_to_mempool(tx_post0)
         send_transaction_to_mempool(tx_post1)
         tx_chain2, _ = create_always_valid_chained_tx(last_chained_output)
         send_transaction_to_mempool(tx_chain2)
         assert_raises_rpc_error(-26, RPC_EXPECTED_ERROR,
                                 node.sendrawtransaction, ToHex(tx_pre1))
         check_mempool_equal([tx_chain1, tx_chain2, tx_post0, tx_post1])
 
         # Mine the 2nd always-valid chained txn and a post-fork-only txn.
         block(5557)
         update_block(5557, [tx_chain1, tx_post0])
         node.p2p.send_blocks_and_test([self.tip], node)
         postforkblockid = node.getbestblockhash()
         # The mempool contains the 3rd chained txn and a post-fork-only txn.
         check_mempool_equal([tx_chain2, tx_post1])
 
         # In the following we will testing block disconnections and reorgs.
         # - tx_chain2 will always be retained in the mempool since it is always
         #   valid. Its continued presence shows that we are never simply
         #   clearing the entire mempool.
         # - tx_post1 may be evicted from mempool if we land before the fork.
         # - tx_post0 is in a block and if 'de-mined', it will either be evicted
         #   or end up in mempool depending if we land before/after the fork.
         # - tx_pre0 is in a block and if 'de-mined', it will either be evicted
         #   or end up in mempool depending if we land after/before the fork.
 
         # First we do a disconnection of the post-fork block, which is a
         # normal disconnection that merely returns the block contents into
         # the mempool -- nothing is lost.
         node.invalidateblock(postforkblockid)
         # In old mempool: tx_chain2, tx_post1
         # Recovered from blocks: tx_chain1 and tx_post0.
         # Lost from blocks: NONE
         # Retained from old mempool: tx_chain2, tx_post1
         # Evicted from old mempool: NONE
         check_mempool_equal([tx_chain1, tx_chain2, tx_post0, tx_post1])
 
         # Now, disconnect the fork block. This is a special disconnection
         # that requires reprocessing the mempool due to change in rules.
         node.invalidateblock(forkblockid)
         # In old mempool: tx_chain1, tx_chain2, tx_post0, tx_post1
         # Recovered from blocks: tx_chain0, tx_pre0
         # Lost from blocks: NONE
         # Retained from old mempool: tx_chain1, tx_chain2
         # Evicted from old mempool: tx_post0, tx_post1
         check_mempool_equal([tx_chain0, tx_chain1, tx_chain2, tx_pre0])
 
         # Restore state
         node.reconsiderblock(postforkblockid)
         node.reconsiderblock(forkblockid)
         send_transaction_to_mempool(tx_post1)
         check_mempool_equal([tx_chain2, tx_post1])
 
         # Test a reorg that crosses the fork.
 
         # If such a reorg happens, most likely it will both start *and end*
         # after the fork. We will test such a case here and make sure that
         # post-fork-only transactions are not unnecessarily discarded from
         # the mempool in such a reorg. Pre-fork-only transactions however can
         # get lost.
 
         # Set up a longer competing chain that doesn't confirm any of our txns.
         # This starts after 5204, so it contains neither the forkblockid nor
         # the postforkblockid from above.
         tip(5204)
         reorg_blocks = []
         for i in range(3):
             reorg_blocks.append(block(5900 + i))
 
         # Perform the reorg
         node.p2p.send_blocks_and_test(reorg_blocks, node)
         # reorg finishes after the fork
         assert_equal(
             node.getblockchaininfo()['mediantime'],
             ACTIVATION_TIME + 2)
         # In old mempool: tx_chain2, tx_post1
         # Recovered from blocks: tx_chain0, tx_chain1, tx_post0
         # Lost from blocks: tx_pre0
         # Retained from old mempool: tx_chain2, tx_post1
         # Evicted from old mempool: NONE
         check_mempool_equal(
             [tx_chain0, tx_chain1, tx_chain2, tx_post0, tx_post1])
 
 
 if __name__ == '__main__':
     MempoolCoherenceOnActivationsTest().main()
diff --git a/test/functional/abc-replay-protection.py b/test/functional/abc-replay-protection.py
index b7ca09aa5..c71ca3c7a 100755
--- a/test/functional/abc-replay-protection.py
+++ b/test/functional/abc-replay-protection.py
@@ -1,320 +1,320 @@
 #!/usr/bin/env python3
 # Copyright (c) 2015-2016 The Bitcoin Core developers
 # Copyright (c) 2017 The Bitcoin developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """
 This test checks activation of UAHF and the different consensus
 related to this activation.
 It is derived from the much more complex p2p-fullblocktest.
 """
 
 import time
 
 from test_framework.blocktools import (
     create_block,
     create_coinbase,
     create_tx_with_script,
     make_conform_to_ctor,
 )
 from test_framework.key import ECKey
 from test_framework.messages import (
     COIN,
     COutPoint,
     CTransaction,
     CTxIn,
     CTxOut,
     ToHex,
 )
 from test_framework.mininode import P2PDataStore
 from test_framework.script import (
     CScript,
     OP_CHECKSIG,
     OP_TRUE,
     SIGHASH_ALL,
     SIGHASH_FORKID,
     SignatureHashForkId,
 )
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal, assert_raises_rpc_error
 
 # far into the future
 REPLAY_PROTECTION_START_TIME = 2000000000
 
 # Error due to invalid signature
-RPC_INVALID_SIGNATURE_ERROR = "mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 16)"
+RPC_INVALID_SIGNATURE_ERROR = "mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)"
 
 
 class PreviousSpendableOutput(object):
 
     def __init__(self, tx=CTransaction(), n=-1):
         self.tx = tx
         self.n = n
 
 
 class ReplayProtectionTest(BitcoinTestFramework):
 
     def set_test_params(self):
         self.num_nodes = 1
         self.setup_clean_chain = True
         self.block_heights = {}
         self.tip = None
         self.blocks = {}
         self.extra_args = [['-whitelist=127.0.0.1',
                             "-replayprotectionactivationtime={}".format(
                                 REPLAY_PROTECTION_START_TIME),
                             "-acceptnonstdtxn=1"]]
 
     def next_block(self, number):
         if self.tip is None:
             base_block_hash = self.genesis_hash
             block_time = int(time.time()) + 1
         else:
             base_block_hash = self.tip.sha256
             block_time = self.tip.nTime + 1
         # First create the coinbase
         height = self.block_heights[base_block_hash] + 1
         coinbase = create_coinbase(height)
         coinbase.rehash()
         block = create_block(base_block_hash, coinbase, block_time)
 
         # Do PoW, which is cheap on regnet
         block.solve()
         self.tip = block
         self.block_heights[block.sha256] = height
         assert number not in self.blocks
         self.blocks[number] = block
         return block
 
     def run_test(self):
         node = self.nodes[0]
         node.add_p2p_connection(P2PDataStore())
         node.setmocktime(REPLAY_PROTECTION_START_TIME)
 
         self.genesis_hash = int(node.getbestblockhash(), 16)
         self.block_heights[self.genesis_hash] = 0
         spendable_outputs = []
 
         # save the current tip so it can be spent by a later block
         def save_spendable_output():
             spendable_outputs.append(self.tip)
 
         # get an output that we previously marked as spendable
         def get_spendable_output():
             return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0)
 
         # move the tip back to a previous block
         def tip(number):
             self.tip = self.blocks[number]
 
         # adds transactions to the block and updates state
         def update_block(block_number, new_transactions):
             block = self.blocks[block_number]
             block.vtx.extend(new_transactions)
             old_sha256 = block.sha256
             make_conform_to_ctor(block)
             block.hashMerkleRoot = block.calc_merkle_root()
             block.solve()
             # Update the internal state just like in next_block
             self.tip = block
             if block.sha256 != old_sha256:
                 self.block_heights[
                     block.sha256] = self.block_heights[old_sha256]
                 del self.block_heights[old_sha256]
             self.blocks[block_number] = block
             return block
 
         # shorthand
         block = self.next_block
 
         # Create a new block
         block(0)
         save_spendable_output()
         node.p2p.send_blocks_and_test([self.tip], node)
 
         # Now we need that block to mature so we can spend the coinbase.
         maturity_blocks = []
         for i in range(99):
             block(5000 + i)
             maturity_blocks.append(self.tip)
             save_spendable_output()
         node.p2p.send_blocks_and_test(maturity_blocks, node)
 
         # collect spendable outputs now to avoid cluttering the code later on
         out = []
         for i in range(100):
             out.append(get_spendable_output())
 
         # Generate a key pair to test P2SH sigops count
         private_key = ECKey()
         private_key.generate()
         public_key = private_key.get_pubkey().get_bytes()
 
         # This is a little handier to use than the version in blocktools.py
         def create_fund_and_spend_tx(spend, forkvalue=0):
             # Fund transaction
             script = CScript([public_key, OP_CHECKSIG])
             txfund = create_tx_with_script(
                 spend.tx, spend.n, b'', amount=50 * COIN - 1000, script_pub_key=script)
             txfund.rehash()
 
             # Spend transaction
             txspend = CTransaction()
             txspend.vout.append(CTxOut(50 * COIN - 2000, CScript([OP_TRUE])))
             txspend.vin.append(CTxIn(COutPoint(txfund.sha256, 0), b''))
 
             # Sign the transaction
             sighashtype = (forkvalue << 8) | SIGHASH_ALL | SIGHASH_FORKID
             sighash = SignatureHashForkId(
                 script, txspend, 0, sighashtype, 50 * COIN - 1000)
             sig = private_key.sign_ecdsa(sighash) + \
                 bytes(bytearray([SIGHASH_ALL | SIGHASH_FORKID]))
             txspend.vin[0].scriptSig = CScript([sig])
             txspend.rehash()
 
             return [txfund, txspend]
 
         def send_transaction_to_mempool(tx):
             tx_id = node.sendrawtransaction(ToHex(tx))
             assert tx_id in set(node.getrawmempool())
             return tx_id
 
         # Before the fork, no replay protection required to get in the mempool.
         txns = create_fund_and_spend_tx(out[0])
         send_transaction_to_mempool(txns[0])
         send_transaction_to_mempool(txns[1])
 
         # And txns get mined in a block properly.
         block(1)
         update_block(1, txns)
         node.p2p.send_blocks_and_test([self.tip], node)
 
         # Replay protected transactions are rejected.
         replay_txns = create_fund_and_spend_tx(out[1], 0xffdead)
         send_transaction_to_mempool(replay_txns[0])
         assert_raises_rpc_error(-26, RPC_INVALID_SIGNATURE_ERROR,
                                 node.sendrawtransaction, ToHex(replay_txns[1]))
 
         # And block containing them are rejected as well.
         block(2)
         update_block(2, replay_txns)
         node.p2p.send_blocks_and_test(
             [self.tip], node, success=False, reject_reason='blk-bad-inputs')
 
         # Rewind bad block
         tip(1)
 
         # Create a block that would activate the replay protection.
         bfork = block(5555)
         bfork.nTime = REPLAY_PROTECTION_START_TIME - 1
         update_block(5555, [])
         node.p2p.send_blocks_and_test([self.tip], node)
 
         activation_blocks = []
         for i in range(5):
             block(5100 + i)
             activation_blocks.append(self.tip)
         node.p2p.send_blocks_and_test(activation_blocks, node)
 
         # Check we are just before the activation time
         assert_equal(
             node.getblockchaininfo()['mediantime'],
             REPLAY_PROTECTION_START_TIME - 1)
 
         # We are just before the fork, replay protected txns still are rejected
         assert_raises_rpc_error(-26, RPC_INVALID_SIGNATURE_ERROR,
                                 node.sendrawtransaction, ToHex(replay_txns[1]))
 
         block(3)
         update_block(3, replay_txns)
         node.p2p.send_blocks_and_test(
             [self.tip], node, success=False, reject_reason='blk-bad-inputs')
 
         # Rewind bad block
         tip(5104)
 
         # Send some non replay protected txns in the mempool to check
         # they get cleaned at activation.
         txns = create_fund_and_spend_tx(out[2])
         send_transaction_to_mempool(txns[0])
         tx_id = send_transaction_to_mempool(txns[1])
 
         # Activate the replay protection
         block(5556)
         node.p2p.send_blocks_and_test([self.tip], node)
 
         # Check we just activated the replay protection
         assert_equal(
             node.getblockchaininfo()['mediantime'],
             REPLAY_PROTECTION_START_TIME)
 
         # Non replay protected transactions are not valid anymore,
         # so they should be removed from the mempool.
         assert tx_id not in set(node.getrawmempool())
 
         # Good old transactions are now invalid.
         send_transaction_to_mempool(txns[0])
         assert_raises_rpc_error(-26, RPC_INVALID_SIGNATURE_ERROR,
                                 node.sendrawtransaction, ToHex(txns[1]))
 
         # They also cannot be mined
         block(4)
         update_block(4, txns)
         node.p2p.send_blocks_and_test(
             [self.tip], node, success=False, reject_reason='blk-bad-inputs')
 
         # Rewind bad block
         tip(5556)
 
         # The replay protected transaction is now valid
         replay_tx0_id = send_transaction_to_mempool(replay_txns[0])
         replay_tx1_id = send_transaction_to_mempool(replay_txns[1])
 
         # Make sure the transaction are ready to be mined.
         tmpl = node.getblocktemplate()
 
         found_id0 = False
         found_id1 = False
 
         for txn in tmpl['transactions']:
             txid = txn['txid']
             if txid == replay_tx0_id:
                 found_id0 = True
             elif txid == replay_tx1_id:
                 found_id1 = True
 
         assert found_id0 and found_id1
 
         # And the mempool is still in good shape.
         assert replay_tx0_id in set(node.getrawmempool())
         assert replay_tx1_id in set(node.getrawmempool())
 
         # They also can also be mined
         block(5)
         update_block(5, replay_txns)
         node.p2p.send_blocks_and_test([self.tip], node)
 
         # Ok, now we check if a reorg work properly across the activation.
         postforkblockid = node.getbestblockhash()
         node.invalidateblock(postforkblockid)
         assert replay_tx0_id in set(node.getrawmempool())
         assert replay_tx1_id in set(node.getrawmempool())
 
         # Deactivating replay protection.
         forkblockid = node.getbestblockhash()
         node.invalidateblock(forkblockid)
         # The funding tx is not evicted from the mempool, since it's valid in
         # both sides of the fork
         assert replay_tx0_id in set(node.getrawmempool())
         assert replay_tx1_id not in set(node.getrawmempool())
 
         # Check that we also do it properly on deeper reorg.
         node.reconsiderblock(forkblockid)
         node.reconsiderblock(postforkblockid)
         node.invalidateblock(forkblockid)
         assert replay_tx0_id in set(node.getrawmempool())
         assert replay_tx1_id not in set(node.getrawmempool())
 
 
 if __name__ == '__main__':
     ReplayProtectionTest().main()
diff --git a/test/functional/abc-segwit-recovery.py b/test/functional/abc-segwit-recovery.py
index 558e43079..b95007ff6 100755
--- a/test/functional/abc-segwit-recovery.py
+++ b/test/functional/abc-segwit-recovery.py
@@ -1,280 +1,280 @@
 #!/usr/bin/env python3
 # Copyright (c) 2019 The Bitcoin developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """
 This test checks that blocks containing segwit recovery transactions will be accepted,
 that segwit recovery transactions are rejected from mempool acceptance (even with
 -acceptnonstdtxn=1), and that segwit recovery transactions don't result in bans.
 """
 
 import time
 
 from test_framework.blocktools import (
     create_block,
     create_coinbase,
     make_conform_to_ctor,
 )
 from test_framework.messages import (
     COIN,
     COutPoint,
     CTransaction,
     CTxIn,
     CTxOut,
     ToHex,
 )
 from test_framework.mininode import (
     P2PDataStore,
 )
 from test_framework.script import (
     CScript,
     hash160,
     OP_EQUAL,
     OP_HASH160,
     OP_TRUE,
 )
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import (
     assert_raises_rpc_error,
 )
 
 TEST_TIME = int(time.time())
 
 # Error due to non clean stack
 CLEANSTACK_ERROR = 'non-mandatory-script-verify-flag (Extra items left on stack after execution)'
-RPC_CLEANSTACK_ERROR = CLEANSTACK_ERROR + " (code 64)"
+RPC_CLEANSTACK_ERROR = CLEANSTACK_ERROR
 EVAL_FALSE_ERROR = 'non-mandatory-script-verify-flag (Script evaluated without error but finished with a false/empty top stack elem'
-RPC_EVAL_FALSE_ERROR = EVAL_FALSE_ERROR + "ent) (code 64)"
+RPC_EVAL_FALSE_ERROR = EVAL_FALSE_ERROR + "ent)"
 
 
 class PreviousSpendableOutput(object):
 
     def __init__(self, tx=CTransaction(), n=-1):
         self.tx = tx
         self.n = n
 
 
 class SegwitRecoveryTest(BitcoinTestFramework):
 
     def set_test_params(self):
         self.num_nodes = 2
         self.setup_clean_chain = True
         self.block_heights = {}
         self.tip = None
         self.blocks = {}
         # We have 2 nodes:
         # 1) node_nonstd (nodes[0]) accepts non-standard txns. It does not
         #    accept Segwit recovery transactions, since it is included in
         #    standard flags, and transactions that violate these flags are
         #    never accepted into the mempool.
         # 2) node_std (nodes[1]) doesn't accept non-standard txns and
         #    doesn't have us whitelisted. It's used to test for bans, as we
         #    connect directly to it via mininode and send a segwit spending
         #    txn. This transaction is non-standard. We check that sending
         #    this transaction doesn't result in a ban.
         # Nodes are connected to each other, so node_std receives blocks and
         # transactions that node_nonstd has accepted. Since we are checking
         # that segwit spending txn are not resulting in bans, node_nonstd
         # doesn't get banned when forwarding this kind of transactions to
         # node_std.
         self.extra_args = [['-whitelist=127.0.0.1',
                             "-acceptnonstdtxn"],
                            ["-acceptnonstdtxn=0"]]
 
     def next_block(self, number):
         if self.tip is None:
             base_block_hash = self.genesis_hash
             block_time = TEST_TIME
         else:
             base_block_hash = self.tip.sha256
             block_time = self.tip.nTime + 1
         # First create the coinbase
         height = self.block_heights[base_block_hash] + 1
         coinbase = create_coinbase(height)
         coinbase.rehash()
         block = create_block(base_block_hash, coinbase, block_time)
 
         # Do PoW, which is cheap on regnet
         block.solve()
         self.tip = block
         self.block_heights[block.sha256] = height
         assert number not in self.blocks
         self.blocks[number] = block
         return block
 
     def bootstrap_p2p(self, *, num_connections=1):
         """Add a P2P connection to the node.
 
         Helper to connect and wait for version handshake."""
         for node in self.nodes:
             for _ in range(num_connections):
                 node.add_p2p_connection(P2PDataStore())
 
     def reconnect_p2p(self, **kwargs):
         """Tear down and bootstrap the P2P connection to the node.
 
         The node gets disconnected several times in this test. This helper
         method reconnects the p2p and restarts the network thread."""
         for node in self.nodes:
             node.disconnect_p2ps()
         self.bootstrap_p2p(**kwargs)
 
     def run_test(self):
         self.bootstrap_p2p()
         self.genesis_hash = int(self.nodes[0].getbestblockhash(), 16)
         self.block_heights[self.genesis_hash] = 0
         spendable_outputs = []
 
         # shorthand
         block = self.next_block
         node_nonstd = self.nodes[0]
         node_std = self.nodes[1]
 
         # save the current tip so it can be spent by a later block
         def save_spendable_output():
             spendable_outputs.append(self.tip)
 
         # get an output that we previously marked as spendable
         def get_spendable_output():
             return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0)
 
         # submit current tip and check it was accepted
         def accepted(node):
             node.p2p.send_blocks_and_test([self.tip], node)
 
         # move the tip back to a previous block
         def tip(number):
             self.tip = self.blocks[number]
 
         # adds transactions to the block and updates state
         def update_block(block_number, new_transactions):
             block = self.blocks[block_number]
             block.vtx.extend(new_transactions)
             old_sha256 = block.sha256
             make_conform_to_ctor(block)
             block.hashMerkleRoot = block.calc_merkle_root()
             block.solve()
             # Update the internal state just like in next_block
             self.tip = block
             if block.sha256 != old_sha256:
                 self.block_heights[
                     block.sha256] = self.block_heights[old_sha256]
                 del self.block_heights[old_sha256]
             self.blocks[block_number] = block
             return block
 
         # checks the mempool has exactly the same txns as in the provided list
         def check_mempool_equal(node, txns):
             assert set(node.getrawmempool()) == set(tx.hash for tx in txns)
 
         # Returns 2 transactions:
         # 1) txfund: create outputs in segwit addresses
         # 2) txspend: spends outputs from segwit addresses
         def create_segwit_fund_and_spend_tx(spend, case0=False):
             if not case0:
                 # Spending from a P2SH-P2WPKH coin,
                 #   txhash:a45698363249312f8d3d93676aa714be59b0bd758e62fa054fb1ea6218480691
                 redeem_script0 = bytearray.fromhex(
                     '0014fcf9969ce1c98a135ed293719721fb69f0b686cb')
                 # Spending from a P2SH-P2WSH coin,
                 #   txhash:6b536caf727ccd02c395a1d00b752098ec96e8ec46c96bee8582be6b5060fa2f
                 redeem_script1 = bytearray.fromhex(
                     '0020fc8b08ed636cb23afcb425ff260b3abd03380a2333b54cfa5d51ac52d803baf4')
             else:
                 redeem_script0 = bytearray.fromhex('51020000')
                 redeem_script1 = bytearray.fromhex('53020080')
             redeem_scripts = [redeem_script0, redeem_script1]
 
             # Fund transaction to segwit addresses
             txfund = CTransaction()
             txfund.vin = [CTxIn(COutPoint(spend.tx.sha256, spend.n))]
             amount = (50 * COIN - 1000) // len(redeem_scripts)
             for redeem_script in redeem_scripts:
                 txfund.vout.append(
                     CTxOut(amount, CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])))
             txfund.rehash()
 
             # Segwit spending transaction
             # We'll test if a node that checks for standardness accepts this
             # txn. It should fail exclusively because of the restriction in
             # the scriptSig (non clean stack..), so all other characteristcs
             # must pass standardness checks. For this reason, we create
             # standard P2SH outputs.
             txspend = CTransaction()
             for i in range(len(redeem_scripts)):
                 txspend.vin.append(
                     CTxIn(COutPoint(txfund.sha256, i), CScript([redeem_scripts[i]])))
             txspend.vout = [CTxOut(50 * COIN - 2000,
                                    CScript([OP_HASH160, hash160(CScript([OP_TRUE])), OP_EQUAL]))]
             txspend.rehash()
 
             return txfund, txspend
 
         # Check we are not banned when sending a txn that is rejected.
         def check_for_no_ban_on_rejected_tx(node, tx, reject_reason):
             node.p2p.send_txs_and_test(
                 [tx], node, success=False, reject_reason=reject_reason)
 
         # Create a new block
         block(0)
         save_spendable_output()
         accepted(node_nonstd)
 
         # Now we need that block to mature so we can spend the coinbase.
         matureblocks = []
         for i in range(199):
             block(5000 + i)
             matureblocks.append(self.tip)
             save_spendable_output()
         node_nonstd.p2p.send_blocks_and_test(matureblocks, node_nonstd)
 
         # collect spendable outputs now to avoid cluttering the code later on
         out = []
         for i in range(100):
             out.append(get_spendable_output())
 
         # Create segwit funding and spending transactions
         txfund, txspend = create_segwit_fund_and_spend_tx(out[0])
         txfund_case0, txspend_case0 = create_segwit_fund_and_spend_tx(
             out[1], True)
 
         # Mine txfund, as it can't go into node_std mempool because it's
         # nonstandard.
         block(5555)
         update_block(5555, [txfund, txfund_case0])
         accepted(node_nonstd)
 
         # Check both nodes are synchronized before continuing.
         self.sync_blocks()
 
         # Check that upgraded nodes checking for standardness are not banning
         # nodes sending segwit spending txns.
         check_for_no_ban_on_rejected_tx(
             node_nonstd, txspend, CLEANSTACK_ERROR)
         check_for_no_ban_on_rejected_tx(
             node_nonstd, txspend_case0, EVAL_FALSE_ERROR)
         check_for_no_ban_on_rejected_tx(
             node_std, txspend, CLEANSTACK_ERROR)
         check_for_no_ban_on_rejected_tx(
             node_std, txspend_case0, EVAL_FALSE_ERROR)
 
         # Segwit recovery txns are never accepted into the mempool,
         # as they are included in standard flags.
         assert_raises_rpc_error(-26, RPC_CLEANSTACK_ERROR,
                                 node_nonstd.sendrawtransaction, ToHex(txspend))
         assert_raises_rpc_error(-26, RPC_EVAL_FALSE_ERROR,
                                 node_nonstd.sendrawtransaction, ToHex(txspend_case0))
         assert_raises_rpc_error(-26, RPC_CLEANSTACK_ERROR,
                                 node_std.sendrawtransaction, ToHex(txspend))
         assert_raises_rpc_error(-26, RPC_EVAL_FALSE_ERROR,
                                 node_std.sendrawtransaction, ToHex(txspend_case0))
 
         # Blocks containing segwit spending txns are accepted in both nodes.
         block(5)
         update_block(5, [txspend, txspend_case0])
         accepted(node_nonstd)
         self.sync_blocks()
 
 
 if __name__ == '__main__':
     SegwitRecoveryTest().main()
diff --git a/test/functional/abc_wallet_standardness.py b/test/functional/abc_wallet_standardness.py
index ca408b309..48a566d8f 100755
--- a/test/functional/abc_wallet_standardness.py
+++ b/test/functional/abc_wallet_standardness.py
@@ -1,194 +1,194 @@
 #!/usr/bin/env python3
 # Copyright (c) 2019 The Bitcoin developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test the response of wallet to a variety of weird / nonstandard coins
 that it might try to spend."""
 
 from decimal import Decimal
 from test_framework.messages import (
     CTransaction,
     CTxOut,
     FromHex,
     ToHex,
 )
 from test_framework.script import (
     CScript,
     OP_1,
     OP_5,
     OP_CHECKSIG,
     OP_CHECKMULTISIG,
     OP_DUP,
     OP_EQUALVERIFY,
     OP_HASH160,
     OP_PUSHDATA1,
     hash160,
 )
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import (
     assert_raises_rpc_error,
     assert_equal,
 )
 
 SATOSHI = Decimal('0.00000001')
 
 
 class WalletStandardnessTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 2
         self.extra_args = [['-acceptnonstdtxn=0'], ['-acceptnonstdtxn=1']]
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def run_test(self):
         std_node, nonstd_node = self.nodes
 
         address_nonstd = nonstd_node.getnewaddress()
 
         # make and mature some coins for the nonstandard node
         nonstd_node.generate(120)
         self.sync_blocks()
 
         def fund_and_test_wallet(scriptPubKey, is_standard, expected_in_std_wallet,
-                                 amount=10000, spendfee=500, nonstd_error="scriptpubkey (code 64)", sign_error=None):
+                                 amount=10000, spendfee=500, nonstd_error="scriptpubkey", sign_error=None):
             """
             Get the nonstandard node to fund a transaction, test its
             standardness by trying to broadcast on the standard node,
             then mine it and see if it ended up in the standard node's wallet.
             Finally, it attempts to spend the coin.
             """
 
             self.log.info("Trying script {}".format(scriptPubKey.hex(),))
 
             # get nonstandard node to fund the script
             tx = CTransaction()
             tx.vout.append(CTxOut(max(amount, 10000), scriptPubKey))
             rawtx = nonstd_node.fundrawtransaction(
                 ToHex(tx), {'lockUnspents': True, 'changePosition': 1})['hex']
             # fundrawtransaction doesn't like to fund dust outputs, so we
             # have to manually override the amount.
             FromHex(tx, rawtx)
             tx.vout[0].nValue = min(amount, 10000)
             rawtx = nonstd_node.signrawtransactionwithwallet(ToHex(tx))['hex']
 
             # ensure signing process did not disturb scriptPubKey
             signedtx = FromHex(CTransaction(), rawtx)
             assert_equal(scriptPubKey, signedtx.vout[0].scriptPubKey)
             txid = signedtx.rehash()
 
             balance_initial = std_node.getbalance()
 
             # try broadcasting it on the standard node
             if is_standard:
                 std_node.sendrawtransaction(rawtx)
                 assert txid in std_node.getrawmempool()
             else:
                 assert_raises_rpc_error(-26, nonstd_error,
                                         std_node.sendrawtransaction, rawtx)
                 assert txid not in std_node.getrawmempool()
 
             # make sure it's in nonstandard node's mempool, then mine it
             nonstd_node.sendrawtransaction(rawtx)
             assert txid in nonstd_node.getrawmempool()
             [blockhash] = nonstd_node.generate(1)
             # make sure it was mined
             assert txid in nonstd_node.getblock(blockhash)["tx"]
 
             self.sync_blocks()
 
             wallet_outpoints = {(entry['txid'], entry['vout'])
                                 for entry in std_node.listunspent()}
 
             # calculate wallet balance change just as a double check
             balance_change = std_node.getbalance() - balance_initial
             if expected_in_std_wallet:
                 assert (txid, 0) in wallet_outpoints
                 assert balance_change == amount * SATOSHI
             else:
                 assert (txid, 0) not in wallet_outpoints
                 assert balance_change == 0
 
             # try spending the funds using the wallet.
             outamount = (amount - spendfee) * SATOSHI
             if outamount < 546 * SATOSHI:
                 # If the final amount would be too small, then just donate
                 # to miner fees.
                 outputs = [{"data": b"to miner, with love".hex()}]
             else:
                 outputs = [{address_nonstd: outamount}]
             spendtx = std_node.createrawtransaction(
                 [{'txid': txid, 'vout': 0}], outputs)
             signresult = std_node.signrawtransactionwithwallet(spendtx)
 
             if sign_error is None:
                 assert_equal(signresult['complete'], True)
                 txid = std_node.sendrawtransaction(signresult['hex'])
                 [blockhash] = std_node.generate(1)
                 # make sure it was mined
                 assert txid in std_node.getblock(blockhash)["tx"]
                 self.sync_blocks()
             else:
                 assert_equal(signresult['complete'], False)
                 assert_equal(signresult['errors'][0]['error'], sign_error)
 
         # we start with an empty wallet
         assert_equal(std_node.getbalance(), 0)
 
         address = std_node.getnewaddress()
         pubkey = bytes.fromhex(std_node.getaddressinfo(address)['pubkey'])
         pubkeyhash = hash160(pubkey)
 
         # P2PK
         fund_and_test_wallet(CScript([pubkey, OP_CHECKSIG]), True, True)
         fund_and_test_wallet(
             CScript([OP_PUSHDATA1, pubkey, OP_CHECKSIG]), False, False,
             sign_error='Data push larger than necessary')
 
         # P2PKH
         fund_and_test_wallet(CScript(
             [OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG]), True, True)
         # The signing error changes here since the script check (with empty
         # scriptSig) hits OP_DUP before it hits the nonminimal push; in all
         # other cases we hit the nonminimal push first.
         fund_and_test_wallet(CScript(
             [OP_DUP, OP_HASH160, OP_PUSHDATA1, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG]), False, False,
             sign_error='Unable to sign input, invalid stack size (possibly missing key)')
 
         # Bare multisig
         fund_and_test_wallet(
             CScript([OP_1, pubkey, OP_1, OP_CHECKMULTISIG]), True, False)
         fund_and_test_wallet(
             CScript([OP_1, OP_PUSHDATA1, pubkey, OP_1,
                      OP_CHECKMULTISIG]), False, False,
             sign_error='Data push larger than necessary')
         fund_and_test_wallet(
             CScript([OP_1, pubkey, b'\x01', OP_CHECKMULTISIG]), False, False,
             sign_error='Data push larger than necessary')
         fund_and_test_wallet(
             CScript([b'\x01', pubkey, OP_1, OP_CHECKMULTISIG]), False, False,
             sign_error='Data push larger than necessary')
         # Note: 1-of-5 is nonstandard to fund yet is standard to spend. However,
         # trying to spend it with our wallet in particular will generate
         # too-dense sigchecks since our wallet currently only signs with ECDSA
         # (Schnorr would not have this issue).
         fund_and_test_wallet(
             CScript([OP_1, pubkey, pubkey, pubkey, pubkey, pubkey,
                      OP_5, OP_CHECKMULTISIG]), False, False,
             sign_error='Input SigChecks limit exceeded')
         fund_and_test_wallet(
             CScript([OP_1, pubkey, pubkey, pubkey, OP_PUSHDATA1,
                      pubkey, pubkey, OP_5, OP_CHECKMULTISIG]), False, False,
             sign_error='Data push larger than necessary')
 
         # Dust also is nonstandard to fund but standard to spend.
         fund_and_test_wallet(
-            CScript([pubkey, OP_CHECKSIG]), False, True, amount=200, nonstd_error="dust (code 64)")
+            CScript([pubkey, OP_CHECKSIG]), False, True, amount=200, nonstd_error="dust")
 
         # and we end with an empty wallet
         assert_equal(std_node.getbalance(), 0)
 
 
 if __name__ == '__main__':
     WalletStandardnessTest().main()
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index c0ee2fa4a..c65b3f70a 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -1,493 +1,493 @@
 #!/usr/bin/env python3
 # Copyright (c) 2014-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test BIP68 implementation."""
 
 import time
 
 from test_framework.blocktools import (
     create_block,
     create_coinbase,
 )
 from test_framework.messages import (
     COIN,
     COutPoint,
     CTransaction,
     CTxIn,
     CTxOut,
     FromHex,
     ToHex,
 )
 from test_framework.script import CScript
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.txtools import pad_tx
 from test_framework.util import (
     assert_equal,
     assert_greater_than,
     assert_raises_rpc_error,
     connect_nodes,
     disconnect_nodes,
     satoshi_round,
 )
 
 SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31)
 # this means use time (0 means height)
 SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22)
 # this is a bit-shift
 SEQUENCE_LOCKTIME_GRANULARITY = 9
 SEQUENCE_LOCKTIME_MASK = 0x0000ffff
 
 # RPC error for non-BIP68 final transactions
-NOT_FINAL_ERROR = "non-BIP68-final (code 64)"
+NOT_FINAL_ERROR = "non-BIP68-final"
 
 
 class BIP68Test(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 2
         self.extra_args = [["-noparkdeepreorg", "-maxreorgdepth=-1", "-acceptnonstdtxn=1"],
                            ["-acceptnonstdtxn=0", "-maxreorgdepth=-1"]]
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def run_test(self):
         self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
 
         # Generate some coins
         self.nodes[0].generate(110)
 
         self.log.info("Running test disable flag")
         self.test_disable_flag()
 
         self.log.info("Running test sequence-lock-confirmed-inputs")
         self.test_sequence_lock_confirmed_inputs()
 
         self.log.info("Running test sequence-lock-unconfirmed-inputs")
         self.test_sequence_lock_unconfirmed_inputs()
 
         self.log.info(
             "Running test BIP68 not consensus before versionbits activation")
         self.test_bip68_not_consensus()
 
         self.log.info("Activating BIP68 (and 112/113)")
         self.activateCSV()
 
         print("Verifying nVersion=2 transactions are standard.")
         print("Note that with current versions of bitcoin software, nVersion=2 transactions are always standard (independent of BIP68 activation status).")
         self.test_version2_relay()
 
         self.log.info("Passed")
 
     # Test that BIP68 is not in effect if tx version is 1, or if
     # the first sequence bit is set.
     def test_disable_flag(self):
         # Create some unconfirmed inputs
         new_addr = self.nodes[0].getnewaddress()
         # send 2 BCH
         self.nodes[0].sendtoaddress(new_addr, 2)
 
         utxos = self.nodes[0].listunspent(0, 0)
         assert len(utxos) > 0
 
         utxo = utxos[0]
 
         tx1 = CTransaction()
         value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN)
 
         # Check that the disable flag disables relative locktime.
         # If sequence locks were used, this would require 1 block for the
         # input to mature.
         sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
         tx1.vin = [
             CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
         tx1.vout = [CTxOut(value, CScript([b'a']))]
         pad_tx(tx1)
 
         tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))[
             "hex"]
         tx1_id = self.nodes[0].sendrawtransaction(tx1_signed)
         tx1_id = int(tx1_id, 16)
 
         # This transaction will enable sequence-locks, so this transaction should
         # fail
         tx2 = CTransaction()
         tx2.nVersion = 2
         sequence_value = sequence_value & 0x7fffffff
         tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
         tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a']))]
         pad_tx(tx2)
         tx2.rehash()
 
         assert_raises_rpc_error(-26, NOT_FINAL_ERROR,
                                 self.nodes[0].sendrawtransaction, ToHex(tx2))
 
         # Setting the version back down to 1 should disable the sequence lock,
         # so this should be accepted.
         tx2.nVersion = 1
 
         self.nodes[0].sendrawtransaction(ToHex(tx2))
 
     # Calculate the median time past of a prior block ("confirmations" before
     # the current tip).
     def get_median_time_past(self, confirmations):
         block_hash = self.nodes[0].getblockhash(
             self.nodes[0].getblockcount() - confirmations)
         return self.nodes[0].getblockheader(block_hash)["mediantime"]
 
     # Test that sequence locks are respected for transactions spending
     # confirmed inputs.
     def test_sequence_lock_confirmed_inputs(self):
         # Create lots of confirmed utxos, and use them to generate lots of random
         # transactions.
         max_outputs = 50
         addresses = []
         while len(addresses) < max_outputs:
             addresses.append(self.nodes[0].getnewaddress())
         while len(self.nodes[0].listunspent()) < 200:
             import random
             random.shuffle(addresses)
             num_outputs = random.randint(1, max_outputs)
             outputs = {}
             for i in range(num_outputs):
                 outputs[addresses[i]] = random.randint(1, 20) * 0.01
             self.nodes[0].sendmany("", outputs)
             self.nodes[0].generate(1)
 
         utxos = self.nodes[0].listunspent()
 
         # Try creating a lot of random transactions.
         # Each time, choose a random number of inputs, and randomly set
         # some of those inputs to be sequence locked (and randomly choose
         # between height/time locking). Small random chance of making the locks
         # all pass.
         for i in range(400):
             # Randomly choose up to 10 inputs
             num_inputs = random.randint(1, 10)
             random.shuffle(utxos)
 
             # Track whether any sequence locks used should fail
             should_pass = True
 
             # Track whether this transaction was built with sequence locks
             using_sequence_locks = False
 
             tx = CTransaction()
             tx.nVersion = 2
             value = 0
             for j in range(num_inputs):
                 # this disables sequence locks
                 sequence_value = 0xfffffffe
 
                 # 50% chance we enable sequence locks
                 if random.randint(0, 1):
                     using_sequence_locks = True
 
                     # 10% of the time, make the input sequence value pass
                     input_will_pass = (random.randint(1, 10) == 1)
                     sequence_value = utxos[j]["confirmations"]
                     if not input_will_pass:
                         sequence_value += 1
                         should_pass = False
 
                     # Figure out what the median-time-past was for the confirmed input
                     # Note that if an input has N confirmations, we're going back N blocks
                     # from the tip so that we're looking up MTP of the block
                     # PRIOR to the one the input appears in, as per the BIP68
                     # spec.
                     orig_time = self.get_median_time_past(
                         utxos[j]["confirmations"])
                     # MTP of the tip
                     cur_time = self.get_median_time_past(0)
 
                     # can only timelock this input if it's not too old --
                     # otherwise use height
                     can_time_lock = True
                     if ((cur_time - orig_time)
                             >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK:
                         can_time_lock = False
 
                     # if time-lockable, then 50% chance we make this a time
                     # lock
                     if random.randint(0, 1) and can_time_lock:
                         # Find first time-lock value that fails, or latest one
                         # that succeeds
                         time_delta = sequence_value << SEQUENCE_LOCKTIME_GRANULARITY
                         if input_will_pass and time_delta > cur_time - orig_time:
                             sequence_value = (
                                 (cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)
                         elif (not input_will_pass and time_delta <= cur_time - orig_time):
                             sequence_value = (
                                 (cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) + 1
                         sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
                 tx.vin.append(
                     CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value))
                 value += utxos[j]["amount"] * COIN
             # Overestimate the size of the tx - signatures should be less than
             # 120 bytes, and leave 50 for the output
             tx_size = len(ToHex(tx)) // 2 + 120 * num_inputs + 50
             tx.vout.append(
                 CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), CScript([b'a'])))
             rawtx = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))[
                 "hex"]
 
             if (using_sequence_locks and not should_pass):
                 # This transaction should be rejected
                 assert_raises_rpc_error(-26, NOT_FINAL_ERROR,
                                         self.nodes[0].sendrawtransaction, rawtx)
             else:
                 # This raw transaction should be accepted
                 self.nodes[0].sendrawtransaction(rawtx)
                 utxos = self.nodes[0].listunspent()
 
     # Test that sequence locks on unconfirmed inputs must have nSequence
     # height or time of 0 to be accepted.
     # Then test that BIP68-invalid transactions are removed from the mempool
     # after a reorg.
     def test_sequence_lock_unconfirmed_inputs(self):
         # Store height so we can easily reset the chain at the end of the test
         cur_height = self.nodes[0].getblockcount()
 
         # Create a mempool tx.
         txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
         tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
         tx1.rehash()
 
         # As the fees are calculated prior to the transaction being signed,
         # there is some uncertainty that calculate fee provides the correct
         # minimal fee. Since regtest coins are free, let's go ahead and
         # increase the fee by an order of magnitude to ensure this test
         # passes.
         fee_multiplier = 10
 
         # Anyone-can-spend mempool tx.
         # Sequence lock of 0 should pass.
         tx2 = CTransaction()
         tx2.nVersion = 2
         tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
         tx2.vout = [
             CTxOut(int(0), CScript([b'a']))]
         tx2.vout[0].nValue = tx1.vout[0].nValue - \
             fee_multiplier * self.nodes[0].calculate_fee(tx2)
         tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"]
         tx2 = FromHex(tx2, tx2_raw)
         tx2.rehash()
         self.nodes[0].sendrawtransaction(tx2_raw)
 
         # Create a spend of the 0th output of orig_tx with a sequence lock
         # of 1, and test what happens when submitting.
         # orig_tx.vout[0] must be an anyone-can-spend output
         def test_nonzero_locks(orig_tx, node, use_height_lock):
             sequence_value = 1
             if not use_height_lock:
                 sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
 
             tx = CTransaction()
             tx.nVersion = 2
             tx.vin = [
                 CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
             tx.vout = [
                 CTxOut(int(orig_tx.vout[0].nValue - fee_multiplier * node.calculate_fee(tx)), CScript([b'a']))]
             pad_tx(tx)
             tx.rehash()
 
             if (orig_tx.hash in node.getrawmempool()):
                 # sendrawtransaction should fail if the tx is in the mempool
                 assert_raises_rpc_error(-26, NOT_FINAL_ERROR,
                                         node.sendrawtransaction, ToHex(tx))
             else:
                 # sendrawtransaction should succeed if the tx is not in the
                 # mempool
                 node.sendrawtransaction(ToHex(tx))
 
             return tx
 
         test_nonzero_locks(
             tx2, self.nodes[0], use_height_lock=True)
         test_nonzero_locks(
             tx2, self.nodes[0], use_height_lock=False)
 
         # Now mine some blocks, but make sure tx2 doesn't get mined.
         # Use prioritisetransaction to lower the effective feerate to 0
         self.nodes[0].prioritisetransaction(
             txid=tx2.hash, fee_delta=-fee_multiplier * self.nodes[0].calculate_fee(tx2))
         cur_time = int(time.time())
         for i in range(10):
             self.nodes[0].setmocktime(cur_time + 600)
             self.nodes[0].generate(1)
             cur_time += 600
 
         assert tx2.hash in self.nodes[0].getrawmempool()
 
         test_nonzero_locks(
             tx2, self.nodes[0], use_height_lock=True)
         test_nonzero_locks(
             tx2, self.nodes[0], use_height_lock=False)
 
         # Mine tx2, and then try again
         self.nodes[0].prioritisetransaction(
             txid=tx2.hash, fee_delta=fee_multiplier * self.nodes[0].calculate_fee(tx2))
 
         # Advance the time on the node so that we can test timelocks
         self.nodes[0].setmocktime(cur_time + 600)
         self.nodes[0].generate(1)
         assert tx2.hash not in self.nodes[0].getrawmempool()
 
         # Now that tx2 is not in the mempool, a sequence locked spend should
         # succeed
         tx3 = test_nonzero_locks(
             tx2, self.nodes[0], use_height_lock=False)
         assert tx3.hash in self.nodes[0].getrawmempool()
 
         self.nodes[0].generate(1)
         assert tx3.hash not in self.nodes[0].getrawmempool()
 
         # One more test, this time using height locks
         tx4 = test_nonzero_locks(
             tx3, self.nodes[0], use_height_lock=True)
         assert tx4.hash in self.nodes[0].getrawmempool()
 
         # Now try combining confirmed and unconfirmed inputs
         tx5 = test_nonzero_locks(
             tx4, self.nodes[0], use_height_lock=True)
         assert tx5.hash not in self.nodes[0].getrawmempool()
 
         utxos = self.nodes[0].listunspent()
         tx5.vin.append(
             CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1))
         tx5.vout[0].nValue += int(utxos[0]["amount"] * COIN)
         raw_tx5 = self.nodes[0].signrawtransactionwithwallet(ToHex(tx5))["hex"]
 
         assert_raises_rpc_error(-26, NOT_FINAL_ERROR,
                                 self.nodes[0].sendrawtransaction, raw_tx5)
 
         # Test mempool-BIP68 consistency after reorg
         #
         # State of the transactions in the last blocks:
         # ... -> [ tx2 ] ->  [ tx3 ]
         #         tip-1        tip
         # And currently tx4 is in the mempool.
         #
         # If we invalidate the tip, tx3 should get added to the mempool, causing
         # tx4 to be removed (fails sequence-lock).
         self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
         assert tx4.hash not in self.nodes[0].getrawmempool()
         assert tx3.hash in self.nodes[0].getrawmempool()
 
         # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
         # diagram above).
         # This would cause tx2 to be added back to the mempool, which in turn causes
         # tx3 to be removed.
         tip = int(self.nodes[0].getblockhash(
             self.nodes[0].getblockcount() - 1), 16)
         height = self.nodes[0].getblockcount()
         for i in range(2):
             block = create_block(tip, create_coinbase(height), cur_time)
             block.nVersion = 3
             block.rehash()
             block.solve()
             tip = block.sha256
             height += 1
             self.nodes[0].submitblock(ToHex(block))
             cur_time += 1
 
         mempool = self.nodes[0].getrawmempool()
         assert tx3.hash not in mempool
         assert tx2.hash in mempool
 
         # Reset the chain and get rid of the mocktimed-blocks
         self.nodes[0].setmocktime(0)
         self.nodes[0].invalidateblock(
             self.nodes[0].getblockhash(cur_height + 1))
         self.nodes[0].generate(10)
 
     def get_csv_status(self):
         height = self.nodes[0].getblockchaininfo()['blocks']
         return height >= 576
 
     # Make sure that BIP68 isn't being used to validate blocks, prior to
     # versionbits activation.  If more blocks are mined prior to this test
     # being run, then it's possible the test has activated the soft fork, and
     # this test should be moved to run earlier, or deleted.
     def test_bip68_not_consensus(self):
         assert_equal(self.get_csv_status(), False)
         txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
 
         tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
         tx1.rehash()
 
         # Make an anyone-can-spend transaction
         tx2 = CTransaction()
         tx2.nVersion = 1
         tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
         tx2.vout = [
             CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))]
 
         # sign tx2
         tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"]
         tx2 = FromHex(tx2, tx2_raw)
         pad_tx(tx2)
         tx2.rehash()
 
         self.nodes[0].sendrawtransaction(ToHex(tx2))
 
         # Now make an invalid spend of tx2 according to BIP68
         # 100 block relative locktime
         sequence_value = 100
 
         tx3 = CTransaction()
         tx3.nVersion = 2
         tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
         tx3.vout = [
             CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))]
         pad_tx(tx3)
         tx3.rehash()
 
         assert_raises_rpc_error(-26, NOT_FINAL_ERROR,
                                 self.nodes[0].sendrawtransaction, ToHex(tx3))
 
         # make a block that violates bip68; ensure that the tip updates
         tip = int(self.nodes[0].getbestblockhash(), 16)
         block = create_block(
             tip, create_coinbase(self.nodes[0].getblockcount() + 1))
         block.nVersion = 3
         block.vtx.extend(
             sorted([tx1, tx2, tx3], key=lambda tx: tx.get_id()))
         block.hashMerkleRoot = block.calc_merkle_root()
         block.rehash()
         block.solve()
 
         self.nodes[0].submitblock(ToHex(block))
         assert_equal(self.nodes[0].getbestblockhash(), block.hash)
 
     def activateCSV(self):
         # activation should happen at block height 576
         csv_activation_height = 576
         height = self.nodes[0].getblockcount()
         assert_greater_than(csv_activation_height - height, 1)
         self.nodes[0].generate(csv_activation_height - height - 1)
         assert_equal(self.get_csv_status(), False)
         disconnect_nodes(self.nodes[0], self.nodes[1])
         self.nodes[0].generate(1)
         assert_equal(self.get_csv_status(), True)
         # We have a block that has CSV activated, but we want to be at
         # the activation point, so we invalidate the tip.
         self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
         connect_nodes(self.nodes[0], self.nodes[1])
         self.sync_blocks()
 
     # Use self.nodes[1] to test that version 2 transactions are standard.
     def test_version2_relay(self):
         inputs = []
         outputs = {self.nodes[1].getnewaddress(): 1.0}
         rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
         rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
         tx = FromHex(CTransaction(), rawtxfund)
         tx.nVersion = 2
         tx_signed = self.nodes[1].signrawtransactionwithwallet(ToHex(tx))[
             "hex"]
         self.nodes[1].sendrawtransaction(tx_signed)
 
 
 if __name__ == '__main__':
     BIP68Test().main()
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index f3bef7598..6002b445b 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -1,218 +1,218 @@
 #!/usr/bin/env python3
 # Copyright (c) 2015-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test BIP65 (CHECKLOCKTIMEVERIFY).
 
 Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height
 1351.
 """
 
 from test_framework.blocktools import create_block, create_coinbase, create_transaction, make_conform_to_ctor
 from test_framework.messages import (
     CTransaction,
     FromHex,
     msg_block,
     msg_tx,
     ToHex,
 )
 from test_framework.mininode import (
     P2PInterface,
 )
 from test_framework.script import (
     CScript,
     CScriptNum,
     OP_1NEGATE,
     OP_CHECKLOCKTIMEVERIFY,
     OP_DROP,
     OP_TRUE,
 )
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.txtools import pad_tx
 from test_framework.util import assert_equal
 
 CLTV_HEIGHT = 1351
 
 
 def cltv_lock_to_height(node, tx, to_address, amount, height=-1):
     '''Modify the scriptPubKey to add an OP_CHECKLOCKTIMEVERIFY, and make
     a transaction that spends it.
 
     This transforms the output script to anyone can spend (OP_TRUE) if the
     lock time condition is valid.
 
     Default height is -1 which leads CLTV to fail
 
     TODO: test more ways that transactions using CLTV could be invalid (eg
     locktime requirements fail, sequence time requirements fail, etc).
     '''
     height_op = OP_1NEGATE
     if(height > 0):
         tx.vin[0].nSequence = 0
         tx.nLockTime = height
         height_op = CScriptNum(height)
 
     tx.vout[0].scriptPubKey = CScript(
         [height_op, OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_TRUE])
 
     pad_tx(tx)
     fundtx_raw = node.signrawtransactionwithwallet(ToHex(tx))['hex']
 
     fundtx = FromHex(CTransaction(), fundtx_raw)
     fundtx.rehash()
 
     # make spending tx
     inputs = [{
         "txid": fundtx.hash,
         "vout": 0
     }]
     output = {to_address: amount}
 
     spendtx_raw = node.createrawtransaction(inputs, output)
 
     spendtx = FromHex(CTransaction(), spendtx_raw)
     pad_tx(spendtx)
 
     return fundtx, spendtx
 
 
 class BIP65Test(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 1
         self.extra_args = [[
             '-whitelist=127.0.0.1',
             '-par=1',  # Use only one script thread to get the exact reject reason for testing
             '-acceptnonstdtxn=1',  # cltv_invalidate is nonstandard
         ]]
         self.setup_clean_chain = True
         self.rpc_timeout = 120
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def run_test(self):
         self.nodes[0].add_p2p_connection(P2PInterface())
 
         self.log.info("Mining {} blocks".format(CLTV_HEIGHT - 2))
         self.coinbase_txids = [self.nodes[0].getblock(
             b)['tx'][0] for b in self.nodes[0].generate(CLTV_HEIGHT - 2)]
         self.nodeaddress = self.nodes[0].getnewaddress()
 
         self.log.info(
             "Test that an invalid-according-to-CLTV transaction can still appear in a block")
 
         fundtx = create_transaction(self.nodes[0], self.coinbase_txids[0],
                                     self.nodeaddress, amount=49.99)
         fundtx, spendtx = cltv_lock_to_height(
             self.nodes[0], fundtx, self.nodeaddress, 49.98)
 
         tip = self.nodes[0].getbestblockhash()
         block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
         block = create_block(int(tip, 16), create_coinbase(
             CLTV_HEIGHT - 1), block_time)
         block.nVersion = 3
         block.vtx.append(fundtx)
         # include the -1 CLTV in block
         block.vtx.append(spendtx)
         make_conform_to_ctor(block)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.solve()
 
         self.nodes[0].p2p.send_and_ping(msg_block(block))
         # This block is valid
         assert_equal(self.nodes[0].getbestblockhash(), block.hash)
 
         self.log.info("Test that blocks must now be at least version 4")
         tip = block.sha256
         block_time += 1
         block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time)
         block.nVersion = 3
         block.solve()
 
         with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000003)'.format(block.hash)]):
             self.nodes[0].p2p.send_and_ping(msg_block(block))
             assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
             self.nodes[0].p2p.sync_with_ping()
 
         self.log.info(
             "Test that invalid-according-to-cltv transactions cannot appear in a block")
         block.nVersion = 4
 
         fundtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
                                     self.nodeaddress, amount=49.99)
         fundtx, spendtx = cltv_lock_to_height(
             self.nodes[0], fundtx, self.nodeaddress, 49.98)
 
         # The funding tx only has unexecuted bad CLTV, in scriptpubkey; this is
         # valid.
         self.nodes[0].p2p.send_and_ping(msg_tx(fundtx))
         assert fundtx.hash in self.nodes[0].getrawmempool()
 
         # Mine a block containing the funding transaction
         block.vtx.append(fundtx)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.solve()
 
         self.nodes[0].p2p.send_and_ping(msg_block(block))
         # This block is valid
         assert_equal(self.nodes[0].getbestblockhash(), block.hash)
 
         # We show that this tx is invalid due to CLTV by getting it
         # rejected from the mempool for exactly that reason.
         assert_equal(
             [{'txid': spendtx.hash, 'allowed': False,
-                'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}],
+              'reject-reason': 'non-mandatory-script-verify-flag (Negative locktime)'}],
             self.nodes[0].testmempoolaccept(
                 rawtxs=[spendtx.serialize().hex()], maxfeerate=0)
         )
 
         rejectedtx_signed = self.nodes[0].signrawtransactionwithwallet(
             ToHex(spendtx))
 
         # Couldn't complete signature due to CLTV
         assert rejectedtx_signed['errors'][0]['error'] == 'Negative locktime'
 
         tip = block.hash
         block_time += 1
         block = create_block(
             block.sha256, create_coinbase(CLTV_HEIGHT + 1), block_time)
         block.nVersion = 4
         block.vtx.append(spendtx)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.solve()
 
         with self.nodes[0].assert_debug_log(expected_msgs=['ConnectBlock {} failed, blk-bad-inputs'.format(block.hash)]):
             self.nodes[0].p2p.send_and_ping(msg_block(block))
             assert_equal(self.nodes[0].getbestblockhash(), tip)
             self.nodes[0].p2p.sync_with_ping()
 
         self.log.info(
             "Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
         fundtx = create_transaction(self.nodes[0], self.coinbase_txids[2],
                                     self.nodeaddress, amount=49.99)
         fundtx, spendtx = cltv_lock_to_height(
             self.nodes[0], fundtx, self.nodeaddress, 49.98, CLTV_HEIGHT)
 
         # make sure sequence is nonfinal and locktime is good
         spendtx.vin[0].nSequence = 0xfffffffe
         spendtx.nLockTime = CLTV_HEIGHT
 
         # both transactions are fully valid
         self.nodes[0].sendrawtransaction(ToHex(fundtx))
         self.nodes[0].sendrawtransaction(ToHex(spendtx))
 
         # Modify the transactions in the block to be valid against CLTV
         block.vtx.pop(1)
         block.vtx.append(fundtx)
         block.vtx.append(spendtx)
         make_conform_to_ctor(block)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.solve()
 
         self.nodes[0].p2p.send_and_ping(msg_block(block))
         # This block is now valid
         assert_equal(self.nodes[0].getbestblockhash(), block.hash)
 
 
 if __name__ == '__main__':
     BIP65Test().main()
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index e5bd4af56..e8ce2df28 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -1,112 +1,112 @@
 #!/usr/bin/env python3
 # Copyright (c) 2015-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test BIP66 (DER SIG).
 
 Test that the DERSIG soft-fork activates at (regtest) height 1251.
 """
 
 from test_framework.blocktools import create_block, create_coinbase, create_transaction
 from test_framework.messages import msg_block
 from test_framework.mininode import P2PInterface
 from test_framework.script import CScript
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal
 
 DERSIG_HEIGHT = 1251
 
 # A canonical signature consists of:
 # <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
 
 
 def unDERify(tx):
     """
     Make the signature in vin 0 of a tx non-DER-compliant,
     by adding padding after the S-value.
     """
     scriptSig = CScript(tx.vin[0].scriptSig)
     newscript = []
     for i in scriptSig:
         if (len(newscript) == 0):
             newscript.append(i[0:-1] + b'\0' + i[-1:])
         else:
             newscript.append(i)
     tx.vin[0].scriptSig = CScript(newscript)
 
 
 class BIP66Test(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 1
         self.extra_args = [['-whitelist=127.0.0.1']]
         self.setup_clean_chain = True
         self.rpc_timeout = 120
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def run_test(self):
         self.nodes[0].add_p2p_connection(P2PInterface())
 
         self.log.info("Mining {} blocks".format(DERSIG_HEIGHT - 1))
         self.coinbase_txids = [self.nodes[0].getblock(
             b)['tx'][0] for b in self.nodes[0].generate(DERSIG_HEIGHT - 1)]
         self.nodeaddress = self.nodes[0].getnewaddress()
 
         self.log.info("Test that blocks must now be at least version 3")
         tip = self.nodes[0].getbestblockhash()
         block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
         block = create_block(
             int(tip, 16), create_coinbase(DERSIG_HEIGHT), block_time)
         block.nVersion = 2
         block.rehash()
         block.solve()
 
         with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000002)'.format(block.hash)]):
             self.nodes[0].p2p.send_and_ping(msg_block(block))
             assert_equal(self.nodes[0].getbestblockhash(), tip)
             self.nodes[0].p2p.sync_with_ping()
 
         self.log.info(
             "Test that transactions with non-DER signatures cannot appear in a block")
         block.nVersion = 3
 
         spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
                                      self.nodeaddress, amount=1.0)
         unDERify(spendtx)
         spendtx.rehash()
 
         # First we show that this tx is valid except for DERSIG by getting it
         # rejected from the mempool for exactly that reason.
         assert_equal(
             [{'txid': spendtx.hash, 'allowed': False,
-                'reject-reason': '16: mandatory-script-verify-flag-failed (Non-canonical DER signature)'}],
+                'reject-reason': 'mandatory-script-verify-flag-failed (Non-canonical DER signature)'}],
             self.nodes[0].testmempoolaccept(
                 rawtxs=[spendtx.serialize().hex()], maxfeerate=0)
         )
 
         # Now we verify that a block with this transaction is also invalid.
         block.vtx.append(spendtx)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.rehash()
         block.solve()
 
         with self.nodes[0].assert_debug_log(expected_msgs=['ConnectBlock {} failed, blk-bad-inputs'.format(block.hash)]):
             self.nodes[0].p2p.send_and_ping(msg_block(block))
             assert_equal(self.nodes[0].getbestblockhash(), tip)
             self.nodes[0].p2p.sync_with_ping()
 
         self.log.info(
             "Test that a version 3 block with a DERSIG-compliant transaction is accepted")
         block.vtx[1] = create_transaction(self.nodes[0],
                                           self.coinbase_txids[1], self.nodeaddress, amount=1.0)
         block.hashMerkleRoot = block.calc_merkle_root()
         block.rehash()
         block.solve()
 
         self.nodes[0].p2p.send_and_ping(msg_block(block))
         assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
 
 
 if __name__ == '__main__':
     BIP66Test().main()
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index a5d0c6a6a..fc76ab78e 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -1,352 +1,352 @@
 #!/usr/bin/env python3
 # Copyright (c) 2017-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test mempool acceptance of raw transactions."""
 
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.messages import (
     COIN,
     COutPoint,
     CTransaction,
     CTxOut,
     FromHex,
     MAX_BLOCK_BASE_SIZE,
     ToHex,
 )
 from test_framework.script import (
     hash160,
     CScript,
     OP_0,
     OP_EQUAL,
     OP_HASH160,
     OP_RETURN,
 )
 from test_framework.util import (
     assert_equal,
     assert_raises_rpc_error,
 )
 
 
 class MempoolAcceptanceTest(BitcoinTestFramework):
     def set_test_params(self):
         self.num_nodes = 1
         self.extra_args = [[
             '-txindex',
             '-acceptnonstdtxn=0',  # Try to mimic main-net
         ]] * self.num_nodes
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def check_mempool_result(self, result_expected, *args, **kwargs):
         """Wrapper to check result of testmempoolaccept on node_0's mempool"""
         result_test = self.nodes[0].testmempoolaccept(*args, **kwargs)
         assert_equal(result_expected, result_test)
         # Must not change mempool state
         assert_equal(self.nodes[0].getmempoolinfo()['size'], self.mempool_size)
 
     def run_test(self):
         node = self.nodes[0]
 
         self.log.info('Start with empty mempool, and 200 blocks')
         self.mempool_size = 0
         assert_equal(node.getblockcount(), 200)
         assert_equal(node.getmempoolinfo()['size'], self.mempool_size)
         coins = node.listunspent()
 
         self.log.info('Should not accept garbage to testmempoolaccept')
         assert_raises_rpc_error(-3, 'Expected type array, got string',
                                 lambda: node.testmempoolaccept(rawtxs='ff00baar'))
         assert_raises_rpc_error(-8, 'Array must contain exactly one raw transaction for now',
                                 lambda: node.testmempoolaccept(rawtxs=['ff00baar', 'ff22']))
         assert_raises_rpc_error(-22, 'TX decode failed',
                                 lambda: node.testmempoolaccept(rawtxs=['ff00baar']))
 
         self.log.info('A transaction already in the blockchain')
         # Pick a random coin(base) to spend
         coin = coins.pop()
         raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction(
             inputs=[{'txid': coin['txid'], 'vout': coin['vout']}],
             outputs=[{node.getnewaddress(): 0.3}, {node.getnewaddress(): 49}],
         ))['hex']
         txid_in_block = node.sendrawtransaction(
             hexstring=raw_tx_in_block, maxfeerate=0)
         node.generate(1)
         self.mempool_size = 0
         self.check_mempool_result(
             result_expected=[{'txid': txid_in_block, 'allowed': False,
-                              'reject-reason': '18: txn-already-known'}],
+                              'reject-reason': 'txn-already-known'}],
             rawtxs=[raw_tx_in_block],
         )
 
         self.log.info('A transaction not in the mempool')
         fee = 0.00000700
         raw_tx_0 = node.signrawtransactionwithwallet(node.createrawtransaction(
             inputs=[{"txid": txid_in_block, "vout": 0,
                      "sequence": 0xfffffffd}],
             outputs=[{node.getnewaddress(): 0.3 - fee}],
         ))['hex']
         tx = FromHex(CTransaction(), raw_tx_0)
         txid_0 = tx.rehash()
         self.check_mempool_result(
             result_expected=[{'txid': txid_0, 'allowed': True}],
             rawtxs=[raw_tx_0],
         )
 
         self.log.info('A final transaction not in the mempool')
         # Pick a random coin(base) to spend
         coin = coins.pop()
         raw_tx_final = node.signrawtransactionwithwallet(node.createrawtransaction(
             inputs=[{'txid': coin['txid'], 'vout': coin['vout'],
                      "sequence": 0xffffffff}],  # SEQUENCE_FINAL
             outputs=[{node.getnewaddress(): 0.025}],
             locktime=node.getblockcount() + 2000,  # Can be anything
         ))['hex']
         tx = FromHex(CTransaction(), raw_tx_final)
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(), 'allowed': True}],
             rawtxs=[tx.serialize().hex()],
             maxfeerate=0,
         )
         node.sendrawtransaction(hexstring=raw_tx_final, maxfeerate=0)
         self.mempool_size += 1
 
         self.log.info('A transaction in the mempool')
         node.sendrawtransaction(hexstring=raw_tx_0)
         self.mempool_size += 1
         self.check_mempool_result(
             result_expected=[{'txid': txid_0, 'allowed': False,
-                              'reject-reason': '18: txn-already-in-mempool'}],
+                              'reject-reason': 'txn-already-in-mempool'}],
             rawtxs=[raw_tx_0],
         )
 
         # Removed RBF test
         # self.log.info('A transaction that replaces a mempool transaction')
         # ...
 
         self.log.info('A transaction that conflicts with an unconfirmed tx')
         # Send the transaction that conflicts with the mempool transaction
         node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0)
         # take original raw_tx_0
         tx = FromHex(CTransaction(), raw_tx_0)
         tx.vout[0].nValue -= int(4 * fee * COIN)  # Set more fee
         # skip re-signing the tx
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(),
                               'allowed': False,
-                              'reject-reason': '18: txn-mempool-conflict'}],
+                              'reject-reason': 'txn-mempool-conflict'}],
             rawtxs=[tx.serialize().hex()],
             maxfeerate=0,
         )
 
         self.log.info('A transaction with missing inputs, that never existed')
         tx = FromHex(CTransaction(), raw_tx_0)
         tx.vin[0].prevout = COutPoint(hash=int('ff' * 32, 16), n=14)
         # skip re-signing the tx
         self.check_mempool_result(
             result_expected=[
                 {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'missing-inputs'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info(
             'A transaction with missing inputs, that existed once in the past')
         tx = FromHex(CTransaction(), raw_tx_0)
         # Set vout to 1, to spend the other outpoint (49 coins) of the
         # in-chain-tx we want to double spend
         tx.vin[0].prevout.n = 1
         raw_tx_1 = node.signrawtransactionwithwallet(
             ToHex(tx))['hex']
         txid_1 = node.sendrawtransaction(hexstring=raw_tx_1, maxfeerate=0)
         # Now spend both to "clearly hide" the outputs, ie. remove the coins
         # from the utxo set by spending them
         raw_tx_spend_both = node.signrawtransactionwithwallet(node.createrawtransaction(
             inputs=[
                 {'txid': txid_0, 'vout': 0},
                 {'txid': txid_1, 'vout': 0},
             ],
             outputs=[{node.getnewaddress(): 0.1}]
         ))['hex']
         txid_spend_both = node.sendrawtransaction(
             hexstring=raw_tx_spend_both, maxfeerate=0)
         node.generate(1)
         self.mempool_size = 0
         # Now see if we can add the coins back to the utxo set by sending the
         # exact txs again
         self.check_mempool_result(
             result_expected=[
                 {'txid': txid_0, 'allowed': False, 'reject-reason': 'missing-inputs'}],
             rawtxs=[raw_tx_0],
         )
         self.check_mempool_result(
             result_expected=[
                 {'txid': txid_1, 'allowed': False, 'reject-reason': 'missing-inputs'}],
             rawtxs=[raw_tx_1],
         )
 
         self.log.info('Create a signed "reference" tx for later use')
         raw_tx_reference = node.signrawtransactionwithwallet(node.createrawtransaction(
             inputs=[{'txid': txid_spend_both, 'vout': 0}],
             outputs=[{node.getnewaddress(): 0.05}],
         ))['hex']
         tx = FromHex(CTransaction(), raw_tx_reference)
         # Reference tx should be valid on itself
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(), 'allowed': True}],
             rawtxs=[ToHex(tx)],
             maxfeerate=0,
         )
 
         self.log.info('A transaction with no outputs')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout = []
         # Skip re-signing the transaction for context independent checks from now on
         # FromHex(tx, node.signrawtransactionwithwallet(ToHex(tx))['hex'])
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '16: bad-txns-vout-empty'}],
+            ), 'allowed': False, 'reject-reason': 'bad-txns-vout-empty'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A really large transaction')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vin = [tx.vin[0]] * (1 + MAX_BLOCK_BASE_SIZE
                                 // len(tx.vin[0].serialize()))
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-oversize'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-oversize'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A transaction with negative output value')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout[0].nValue *= -1
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '16: bad-txns-vout-negative'}],
+            ), 'allowed': False, 'reject-reason': 'bad-txns-vout-negative'}],
             rawtxs=[ToHex(tx)],
         )
 
         # The following two validations prevent overflow of the output amounts
         # (see CVE-2010-5139).
         self.log.info('A transaction with too large output value')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout[0].nValue = 21000000 * COIN + 1
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '16: bad-txns-vout-toolarge'}],
+            ), 'allowed': False, 'reject-reason': 'bad-txns-vout-toolarge'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A transaction with too large sum of output values')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout = [tx.vout[0]] * 2
         tx.vout[0].nValue = 21000000 * COIN
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '16: bad-txns-txouttotal-toolarge'}],
+            ), 'allowed': False, 'reject-reason': 'bad-txns-txouttotal-toolarge'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A transaction with duplicate inputs')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vin = [tx.vin[0]] * 2
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '16: bad-txns-inputs-duplicate'}],
+            ), 'allowed': False, 'reject-reason': 'bad-txns-inputs-duplicate'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A coinbase transaction')
         # Pick the input of the first tx we signed, so it has to be a coinbase
         # tx
         raw_tx_coinbase_spent = node.getrawtransaction(
             txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid'])
         tx = FromHex(CTransaction(), raw_tx_coinbase_spent)
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-tx-coinbase'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-tx-coinbase'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('Some nonstandard transactions')
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.nVersion = 3  # A version currently non-standard
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: version'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'version'}],
             rawtxs=[ToHex(tx)],
         )
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout[0].scriptPubKey = CScript([OP_0])  # Some non-standard script
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: scriptpubkey'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'scriptpubkey'}],
             rawtxs=[ToHex(tx)],
         )
         tx = FromHex(CTransaction(), raw_tx_reference)
         # Some not-pushonly scriptSig
         tx.vin[0].scriptSig = CScript([OP_HASH160])
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(
-            ), 'allowed': False, 'reject-reason': '64: scriptsig-not-pushonly'}],
+            ), 'allowed': False, 'reject-reason': 'scriptsig-not-pushonly'}],
             rawtxs=[ToHex(tx)],
         )
         tx = FromHex(CTransaction(), raw_tx_reference)
         output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=CScript(
             [OP_HASH160, hash160(b'burn'), OP_EQUAL]))
         # Use enough outputs to make the tx too large for our policy
         num_scripts = 100000 // len(output_p2sh_burn.serialize())
         tx.vout = [output_p2sh_burn] * num_scripts
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: tx-size'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'tx-size'}],
             rawtxs=[ToHex(tx)],
         )
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout[0] = output_p2sh_burn
         # Make output smaller, such that it is dust for our policy
         tx.vout[0].nValue -= 1
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: dust'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'dust'}],
             rawtxs=[ToHex(tx)],
         )
         tx = FromHex(CTransaction(), raw_tx_reference)
         tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'\xff'])
         tx.vout = [tx.vout[0]] * 2
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: multi-op-return'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'multi-op-return'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A timelocked transaction')
         tx = FromHex(CTransaction(), raw_tx_reference)
         # Should be non-max, so locktime is not ignored
         tx.vin[0].nSequence -= 1
         tx.nLockTime = node.getblockcount() + 1
         self.check_mempool_result(
             result_expected=[
-                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: bad-txns-nonfinal'}],
+                {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-nonfinal'}],
             rawtxs=[ToHex(tx)],
         )
 
         self.log.info('A transaction that is locked by BIP68 sequence logic')
         tx = FromHex(CTransaction(), raw_tx_reference)
         # We could include it in the second block mined from now, but not the
         # very next one
         tx.vin[0].nSequence = 2
         # Can skip re-signing the tx because of early rejection
         self.check_mempool_result(
             result_expected=[{'txid': tx.rehash(),
                               'allowed': False,
-                              'reject-reason': '64: non-BIP68-final'}],
+                              'reject-reason': 'non-BIP68-final'}],
             rawtxs=[tx.serialize().hex()],
             maxfeerate=0,
         )
 
 
 if __name__ == '__main__':
     MempoolAcceptanceTest().main()
diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py
index f0aeb3aea..c694a8faa 100755
--- a/test/functional/mining_prioritisetransaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -1,221 +1,221 @@
 #!/usr/bin/env python3
 # Copyright (c) 2015-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test the prioritisetransaction mining RPC."""
 
 import time
 
 from test_framework.blocktools import (
     create_confirmed_utxos,
     send_big_transactions,
 )
 # FIXME: review how this test needs to be adapted w.r.t _LEGACY_MAX_BLOCK_SIZE
 from test_framework.cdefs import LEGACY_MAX_BLOCK_SIZE
 from test_framework.messages import COIN
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.util import assert_equal, assert_raises_rpc_error
 
 
 class PrioritiseTransactionTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.num_nodes = 2
         # TODO: remove -txindex. Currently required for getrawtransaction call
         # (called by calculate_fee_from_txid)
         self.extra_args = [[
             "-printpriority=1",
             "-acceptnonstdtxn=1",
             "-txindex"
         ]] * self.num_nodes
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def run_test(self):
         # Test `prioritisetransaction` required parameters
         assert_raises_rpc_error(-1,
                                 "prioritisetransaction",
                                 self.nodes[0].prioritisetransaction)
         assert_raises_rpc_error(-1,
                                 "prioritisetransaction",
                                 self.nodes[0].prioritisetransaction,
                                 '')
         assert_raises_rpc_error(-1,
                                 "prioritisetransaction",
                                 self.nodes[0].prioritisetransaction,
                                 '',
                                 0)
 
         # Test `prioritisetransaction` invalid extra parameters
         assert_raises_rpc_error(-1,
                                 "prioritisetransaction",
                                 self.nodes[0].prioritisetransaction,
                                 '',
                                 0,
                                 0,
                                 0)
 
         # Test `prioritisetransaction` invalid `txid`
         assert_raises_rpc_error(-8,
                                 "txid must be of length 64 (not 3, for 'foo')",
                                 self.nodes[0].prioritisetransaction,
                                 txid='foo',
                                 fee_delta=0)
         assert_raises_rpc_error(
             -8,
             "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')",
             self.nodes[0].prioritisetransaction,
             txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000',
             fee_delta=0)
 
         # Test `prioritisetransaction` invalid `dummy`
         txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
         assert_raises_rpc_error(-1,
                                 "JSON value is not a number as expected",
                                 self.nodes[0].prioritisetransaction,
                                 txid,
                                 'foo',
                                 0)
         assert_raises_rpc_error(
             -8,
             "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.",
             self.nodes[0].prioritisetransaction,
             txid,
             1,
             0)
 
         # Test `prioritisetransaction` invalid `fee_delta`
         assert_raises_rpc_error(-1,
                                 "JSON value is not an integer as expected",
                                 self.nodes[0].prioritisetransaction,
                                 txid=txid,
                                 fee_delta='foo')
 
         self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
 
         utxo_count = 90
         utxos = create_confirmed_utxos(self.nodes[0], utxo_count)
         txids = []
 
         # Create 3 batches of transactions at 3 different fee rate levels
         range_size = utxo_count // 3
         for i in range(3):
             txids.append([])
             start_range = i * range_size
             end_range = start_range + range_size
             txids[i] = send_big_transactions(self.nodes[0], utxos[start_range:end_range],
                                              end_range - start_range, 10 * (i + 1))
 
         # Make sure that the size of each group of transactions exceeds
         # LEGACY_MAX_BLOCK_SIZE -- otherwise the test needs to be revised to create
         # more transactions.
         mempool = self.nodes[0].getrawmempool(True)
         sizes = [0, 0, 0]
         for i in range(3):
             for j in txids[i]:
                 assert j in mempool
                 sizes[i] += mempool[j]['size']
             # Fail => raise utxo_count
             assert sizes[i] > LEGACY_MAX_BLOCK_SIZE
 
         # add a fee delta to something in the cheapest bucket and make sure it gets mined
         # also check that a different entry in the cheapest bucket is NOT mined
         self.nodes[0].prioritisetransaction(
             txid=txids[0][0], fee_delta=100 * self.nodes[0].calculate_fee_from_txid(txids[0][0]))
 
         self.nodes[0].generate(1)
 
         mempool = self.nodes[0].getrawmempool()
         self.log.info("Assert that prioritised transaction was mined")
         assert txids[0][0] not in mempool
         assert txids[0][1] in mempool
 
         confirmed_transactions = self.nodes[0].getblock(
             self.nodes[0].getbestblockhash())['tx']
 
         # Pull the highest fee-rate transaction from a block
         high_fee_tx = confirmed_transactions[1]
 
         # Something high-fee should have been mined!
         assert high_fee_tx is not None
 
         # Add a prioritisation before a tx is in the mempool (de-prioritising a
         # high-fee transaction so that it's now low fee).
         #
         # NOTE WELL: gettransaction returns the fee as a negative number and
         # as fractional coins. However, the prioritisetransaction expects a
         # number of satoshi to add or subtract from the actual fee.
         # Thus the conversation here is simply int(tx_fee*COIN) to remove all fees, and then
         # we add the minimum fee back.
         tx_fee = self.nodes[0].gettransaction(high_fee_tx)['fee']
         self.nodes[0].prioritisetransaction(
             txid=high_fee_tx, fee_delta=int(tx_fee * COIN) + self.nodes[0].calculate_fee_from_txid(high_fee_tx))
 
         # Add everything back to mempool
         self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
 
         # Check to make sure our high fee rate tx is back in the mempool
         mempool = self.nodes[0].getrawmempool()
         assert high_fee_tx in mempool
 
         # Now verify the modified-high feerate transaction isn't mined before
         # the other high fee transactions. Keep mining until our mempool has
         # decreased by all the high fee size that we calculated above.
         while (self.nodes[0].getmempoolinfo()['bytes'] > sizes[0] + sizes[1]):
             self.nodes[0].generate(1)
 
         # High fee transaction should not have been mined, but other high fee rate
         # transactions should have been.
         mempool = self.nodes[0].getrawmempool()
         self.log.info(
             "Assert that de-prioritised transaction is still in mempool")
         assert high_fee_tx in mempool
         for x in txids[2]:
             if (x != high_fee_tx):
                 assert x not in mempool
 
         # Create a free transaction.  Should be rejected.
         utxo_list = self.nodes[0].listunspent()
         assert len(utxo_list) > 0
         utxo = utxo_list[0]
 
         inputs = []
         outputs = {}
         inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
         outputs[self.nodes[0].getnewaddress()] = utxo["amount"]
         raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
         tx_hex = self.nodes[0].signrawtransactionwithwallet(raw_tx)["hex"]
         tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"]
 
         # This will raise an exception due to min relay fee not being met
-        assert_raises_rpc_error(-26, "min relay fee not met (code 66)",
+        assert_raises_rpc_error(-26, "min relay fee not met",
                                 self.nodes[0].sendrawtransaction, tx_hex)
         assert tx_id not in self.nodes[0].getrawmempool()
 
         # This is a less than 1000-byte transaction, so just set the fee
         # to be the minimum for a 1000-byte transaction and check that it is
         # accepted.
         self.nodes[0].prioritisetransaction(
             txid=tx_id, fee_delta=int(self.relayfee * COIN))
 
         self.log.info(
             "Assert that prioritised free transaction is accepted to mempool")
         assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx_id)
         assert tx_id in self.nodes[0].getrawmempool()
 
         # Test that calling prioritisetransaction is sufficient to trigger
         # getblocktemplate to (eventually) return a new block.
         mock_time = int(time.time())
         self.nodes[0].setmocktime(mock_time)
         template = self.nodes[0].getblocktemplate()
         self.nodes[0].prioritisetransaction(
             txid=tx_id, fee_delta=-int(self.relayfee * COIN))
         self.nodes[0].setmocktime(mock_time + 10)
         new_template = self.nodes[0].getblocktemplate()
 
         assert template != new_template
 
 
 if __name__ == '__main__':
     PrioritiseTransactionTest().main()
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py
index 7af073722..cdcd53841 100755
--- a/test/functional/p2p_dos_header_tree.py
+++ b/test/functional/p2p_dos_header_tree.py
@@ -1,96 +1,96 @@
 #!/usr/bin/env python3
 # Copyright (c) 2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test that we reject low difficulty headers to prevent our block tree from filling up with useless bloat"""
 
 from test_framework.messages import (
     CBlockHeader,
     FromHex,
 )
 from test_framework.mininode import (
     P2PInterface,
     msg_headers,
 )
 from test_framework.test_framework import BitcoinTestFramework
 
 import os
 
 
 class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
     def set_test_params(self):
         self.setup_clean_chain = True
         self.chain = 'testnet3'  # Use testnet chain because it has an early checkpoint
         self.num_nodes = 2
 
     def add_options(self, parser):
         parser.add_argument(
             '--datafile',
             default='data/blockheader_testnet3.hex',
             help='Test data file (default: %(default)s)',
         )
 
     def run_test(self):
         self.log.info("Read headers data")
         self.headers_file_path = os.path.join(
             os.path.dirname(
                 os.path.realpath(__file__)),
             self.options.datafile)
         with open(self.headers_file_path, encoding='utf-8') as headers_data:
             h_lines = [line.strip() for line in headers_data.readlines()]
 
         # The headers data is taken from testnet3 for early blocks from genesis until the first checkpoint. There are
         # two headers with valid POW at height 1 and 2, forking off from
         # genesis. They are indicated by the FORK_PREFIX.
         FORK_PREFIX = 'fork:'
         self.headers = [
             line for line in h_lines if not line.startswith(FORK_PREFIX)]
         self.headers_fork = [line[len(FORK_PREFIX):]
                              for line in h_lines if line.startswith(FORK_PREFIX)]
 
         self.headers = [FromHex(CBlockHeader(), h) for h in self.headers]
         self.headers_fork = [FromHex(CBlockHeader(), h)
                              for h in self.headers_fork]
 
         self.log.info(
             "Feed all non-fork headers, including and up to the first checkpoint")
         self.nodes[0].add_p2p_connection(P2PInterface())
         self.nodes[0].p2p.send_and_ping(msg_headers(self.headers))
         assert {
             'height': 546,
             'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70',
             'branchlen': 546,
             'status': 'headers-only',
         } in self.nodes[0].getchaintips()
 
         self.log.info("Feed all fork headers (fails due to checkpoint)")
-        with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint (code 67)']):
+        with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint']):
             self.nodes[0].p2p.send_message(msg_headers(self.headers_fork))
             self.nodes[0].p2p.wait_for_disconnect()
 
         self.log.info("Feed all fork headers (succeeds without checkpoint)")
         # On node 0 it succeeds because checkpoints are disabled
         self.restart_node(0, extra_args=['-nocheckpoints'])
         self.nodes[0].add_p2p_connection(P2PInterface())
         self.nodes[0].p2p.send_and_ping(msg_headers(self.headers_fork))
         assert {
             "height": 2,
             "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
             "branchlen": 2,
             "status": "headers-only",
         } in self.nodes[0].getchaintips()
 
         # On node 1 it succeeds because no checkpoint has been reached yet by a
         # chain tip
         self.nodes[1].add_p2p_connection(P2PInterface())
         self.nodes[1].p2p.send_and_ping(msg_headers(self.headers_fork))
         assert {
             "height": 2,
             "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
             "branchlen": 2,
             "status": "headers-only",
         } in self.nodes[1].getchaintips()
 
 
 if __name__ == '__main__':
     RejectLowDifficultyHeadersTest().main()
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index dcd27cbb8..8ec4fee0f 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -1,684 +1,684 @@
 #!/usr/bin/env python3
 # Copyright (c) 2014-2019 The Bitcoin Core developers
 # Distributed under the MIT software license, see the accompanying
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 """Test the rawtranscation RPCs.
 
 Test the following RPCs:
    - createrawtransaction
    - signrawtransactionwithwallet
    - sendrawtransaction
    - decoderawtransaction
    - getrawtransaction
 """
 
 from decimal import Decimal
 
 from collections import OrderedDict
 from io import BytesIO
 from test_framework.messages import (
     COutPoint,
     CTransaction,
     CTxIn,
     CTxOut,
     ToHex,
 )
 from test_framework.script import CScript
 from test_framework.test_framework import BitcoinTestFramework
 from test_framework.txtools import pad_raw_tx
 from test_framework.util import (
     assert_equal,
     assert_greater_than,
     assert_raises_rpc_error,
     connect_nodes,
     hex_str_to_bytes,
 )
 
 
 class multidict(dict):
     """Dictionary that allows duplicate keys.
     Constructed with a list of (key, value) tuples. When dumped by the json module,
     will output invalid json with repeated keys, eg:
     >>> json.dumps(multidict([(1,2),(1,2)])
     '{"1": 2, "1": 2}'
     Used to test calls to rpc methods with repeated keys in the json object."""
 
     def __init__(self, x):
         dict.__init__(self, x)
         self.x = x
 
     def items(self):
         return self.x
 
 
 # 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
         self.extra_args = [["-txindex"], ["-txindex"], ["-txindex"]]
 
     def skip_test_if_missing_module(self):
         self.skip_if_no_wallet()
 
     def setup_network(self):
         super().setup_network()
         connect_nodes(self.nodes[0], self.nodes[2])
 
     def run_test(self):
         self.log.info(
             '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()
 
         self.log.info(
             'Test getrawtransaction on genesis block coinbase returns an error')
         block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
         assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction",
                                 self.nodes[0].getrawtransaction, block['merkleroot'])
 
         self.log.info(
             'Check parameter types and required parameters of createrawtransaction')
         # Test `createrawtransaction` required parameters
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction)
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction, [])
 
         # Test `createrawtransaction` invalid extra parameters
         assert_raises_rpc_error(-1, "createrawtransaction",
                                 self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
 
         # Test `createrawtransaction` invalid `inputs`
         txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
         assert_raises_rpc_error(-3, "Expected type array",
                                 self.nodes[0].createrawtransaction, 'foo', {})
         assert_raises_rpc_error(-1, "JSON value is not an object as expected",
                                 self.nodes[0].createrawtransaction, ['foo'], {})
         assert_raises_rpc_error(-1,
                                 "JSON value is not a string as expected",
                                 self.nodes[0].createrawtransaction,
                                 [{}],
                                 {})
         assert_raises_rpc_error(-8,
                                 "txid must be of length 64 (not 3, for 'foo')",
                                 self.nodes[0].createrawtransaction,
                                 [{'txid': 'foo'}],
                                 {})
         assert_raises_rpc_error(-8,
                                 "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')",
                                 self.nodes[0].createrawtransaction,
                                 [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}],
                                 {})
         assert_raises_rpc_error(-8, "Invalid parameter, missing vout key",
                                 self.nodes[0].createrawtransaction, [{'txid': txid}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, vout must be a number",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
         assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range",
                                 self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {})
 
         # Test `createrawtransaction` invalid `outputs`
         address = self.nodes[0].getnewaddress()
         address2 = self.nodes[0].getnewaddress()
         assert_raises_rpc_error(-1, "JSON value is not an array as expected",
                                 self.nodes[0].createrawtransaction, [], 'foo')
         # Should not throw for backwards compatibility
         self.nodes[0].createrawtransaction(inputs=[], outputs={})
         self.nodes[0].createrawtransaction(inputs=[], outputs=[])
         assert_raises_rpc_error(-8, "Data must be hexadecimal string",
                                 self.nodes[0].createrawtransaction, [], {'data': 'foo'})
         assert_raises_rpc_error(-5, "Invalid Bitcoin address",
                                 self.nodes[0].createrawtransaction, [], {'foo': 0})
         assert_raises_rpc_error(-3, "Invalid amount",
                                 self.nodes[0].createrawtransaction, [], {address: 'foo'})
         assert_raises_rpc_error(-3, "Amount out of range",
                                 self.nodes[0].createrawtransaction, [], {address: -1})
         assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: {}".format(
             address), self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
         assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: {}".format(
             address), self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}])
         assert_raises_rpc_error(-8,
                                 "Invalid parameter, duplicate key: data",
                                 self.nodes[0].createrawtransaction,
                                 [],
                                 [{"data": 'aa'},
                                     {"data": "bb"}])
         assert_raises_rpc_error(-8,
                                 "Invalid parameter, duplicate key: data",
                                 self.nodes[0].createrawtransaction,
                                 [],
                                 multidict([("data",
                                             'aa'),
                                            ("data",
                                             "bb")]))
         assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key",
                                 self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}])
         assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected",
                                 self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']])
 
         # Test `createrawtransaction` invalid `locktime`
         assert_raises_rpc_error(-3, "Expected type number",
                                 self.nodes[0].createrawtransaction, [], {}, 'foo')
         assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range",
                                 self.nodes[0].createrawtransaction, [], {}, -1)
         assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range",
                                 self.nodes[0].createrawtransaction, [], {}, 4294967296)
 
         self.log.info(
             'Check that createrawtransaction accepts an array and object as outputs')
         tx = CTransaction()
         # One output
         tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(
             inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99}))))
         assert_equal(len(tx.vout), 1)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(
                 inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]),
         )
         # Two outputs
         tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[
                        {'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)])))))
         assert_equal(len(tx.vout), 2)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[
                                                {address: 99}, {address2: 99}]),
         )
         # Multiple mixed outputs
         tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[
                        {'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), (address2, 99), ('data', '99')])))))
         assert_equal(len(tx.vout), 3)
         assert_equal(
             tx.serialize().hex(),
             self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[
                                                {address: 99}, {address2: 99}, {'data': '99'}]),
         )
 
         for type in ["legacy"]:
             addr = self.nodes[0].getnewaddress("", type)
             addrinfo = self.nodes[0].getaddressinfo(addr)
             pubkey = addrinfo["scriptPubKey"]
 
             self.log.info(
                 'sendrawtransaction with missing prevtx info ({})'.format(type))
 
             # Test `signrawtransactionwithwallet` invalid `prevtxs`
             inputs = [{'txid': txid, 'vout': 3, 'sequence': 1000}]
             outputs = {self.nodes[0].getnewaddress(): 1}
             rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
 
             prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1)
             succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
             assert succ["complete"]
 
             assert_raises_rpc_error(-8, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "scriptPubKey": pubkey,
                     "vout": 3,
                 }
             ])
 
             assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "scriptPubKey": pubkey,
                     "amount": 1,
                 }
             ])
             assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "scriptPubKey": pubkey,
                     "vout": 3,
                     "amount": 1,
                 }
             ])
             assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [
                 {
                     "txid": txid,
                     "vout": 3,
                     "amount": 1
                 }
             ])
 
         #########################################
         # sendrawtransaction with missing input #
         #########################################
 
         self.log.info('sendrawtransaction with missing input')
         # won't exists
         inputs = [
             {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1}]
         outputs = {self.nodes[0].getnewaddress(): 4.998}
         rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawtx = pad_raw_tx(rawtx)
         rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
 
         # This will raise an exception since there are missing inputs
         assert_raises_rpc_error(-25,
                                 "bad-txns-inputs-missingorspent",
                                 self.nodes[2].sendrawtransaction,
                                 rawtx['hex'])
 
         #####################################
         # getrawtransaction with block hash #
         #####################################
 
         # make a tx by sending then generate 2 blocks; block1 has the tx in it
         tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1)
         block1, block2 = self.nodes[2].generate(2)
         self.sync_all()
         # We should be able to get the raw transaction by providing the correct
         # block
         gottx = self.nodes[0].getrawtransaction(tx, True, block1)
         assert_equal(gottx['txid'], tx)
         assert_equal(gottx['in_active_chain'], True)
         # We should not have the 'in_active_chain' flag when we don't provide a
         # block
         gottx = self.nodes[0].getrawtransaction(tx, True)
         assert_equal(gottx['txid'], tx)
         assert 'in_active_chain' not in gottx
         # We should not get the tx if we provide an unrelated block
         assert_raises_rpc_error(-5, "No such transaction found",
                                 self.nodes[0].getrawtransaction, tx, True, block2)
         # An invalid block hash should raise the correct errors
         assert_raises_rpc_error(-1,
                                 "JSON value is not a string as expected",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 True)
         assert_raises_rpc_error(-8,
                                 "parameter 3 must be of length 64 (not 6, for 'foobar')",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 "foobar")
         assert_raises_rpc_error(-8,
                                 "parameter 3 must be of length 64 (not 8, for 'abcd1234')",
                                 self.nodes[0].getrawtransaction,
                                 tx,
                                 True,
                                 "abcd1234")
         assert_raises_rpc_error(
             -8,
             "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
             self.nodes[0].getrawtransaction,
             tx,
             True,
             "ZZZ0000000000000000000000000000000000000000000000000000000000000")
         assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction,
                                 tx, True, "0000000000000000000000000000000000000000000000000000000000000000")
         # Undo the blocks and check in_active_chain
         self.nodes[0].invalidateblock(block1)
         gottx = self.nodes[0].getrawtransaction(
             txid=tx, verbose=True, blockhash=block1)
         assert_equal(gottx['in_active_chain'], False)
         self.nodes[0].reconsiderblock(block1)
         assert_equal(self.nodes[0].getbestblockhash(), block2)
 
         #
         # RAW TX MULTISIG TESTS #
         #
         # 2of2 test
         addr1 = self.nodes[2].getnewaddress()
         addr2 = self.nodes[2].getnewaddress()
 
         addr1Obj = self.nodes[2].getaddressinfo(addr1)
         addr2Obj = self.nodes[2].getaddressinfo(addr2)
 
         # Tests for createmultisig and addmultisigaddress
         assert_raises_rpc_error(-5, "Invalid public key",
                                 self.nodes[0].createmultisig, 1, ["01020304"])
         # createmultisig can only take public keys
         self.nodes[0].createmultisig(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
         # addmultisigaddress can take both pubkeys and addresses so long as
         # they are in the wallet, which is tested here.
         assert_raises_rpc_error(-5, "Invalid public key",
                                 self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1])
 
         mSigObj = self.nodes[2].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr1])['address']
 
         # use balance deltas instead of absolute values
         bal = self.nodes[2].getbalance()
 
         # send 1.2 BCH 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].getaddressinfo(addr1)
         addr2Obj = self.nodes[2].getaddressinfo(addr2)
         addr3Obj = self.nodes[2].getaddressinfo(addr3)
 
         mSigObj = self.nodes[2].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
 
         txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
         decTx = self.nodes[0].gettransaction(txId)
         rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
         self.sync_all()
         self.nodes[0].generate(1)
         self.sync_all()
 
         # THIS IS AN 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 = next(o for o in rawTx['vout']
                     if o['value'] == Decimal('2.20000000'))
 
         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].signrawtransactionwithwallet(
             rawTx, inputs)
         # node1 only has one key, can't comp. sign the tx
         assert_equal(rawTxPartialSigned['complete'], False)
 
         rawTxSigned = self.nodes[2].signrawtransactionwithwallet(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
 
         rawTxBlock = self.nodes[0].getblock(self.nodes[0].getbestblockhash())
 
         # 2of2 test for combining transactions
         bal = self.nodes[2].getbalance()
         addr1 = self.nodes[1].getnewaddress()
         addr2 = self.nodes[2].getnewaddress()
 
         addr1Obj = self.nodes[1].getaddressinfo(addr1)
         addr2Obj = self.nodes[2].getaddressinfo(addr2)
 
         self.nodes[1].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
         mSigObj = self.nodes[2].addmultisigaddress(
             2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
         mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
 
         txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
         decTx = self.nodes[0].gettransaction(txId)
         rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
         self.sync_all()
         self.nodes[0].generate(1)
         self.sync_all()
 
         # the funds of a 2of2 multisig tx should not be marked as spendable
         assert_equal(self.nodes[2].getbalance(), bal)
 
         txDetails = self.nodes[0].gettransaction(txId, True)
         rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
         vout = next(o for o in rawTx2['vout']
                     if o['value'] == Decimal('2.20000000'))
 
         bal = self.nodes[0].getbalance()
         inputs = [{"txid": txId, "vout": vout['n'], "scriptPubKey": vout['scriptPubKey']
                    ['hex'], "redeemScript": mSigObjValid['hex'], "amount": vout['value']}]
         outputs = {self.nodes[0].getnewaddress(): 2.19}
         rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(
             rawTx2, inputs)
         self.log.debug(rawTxPartialSigned1)
         # node1 only has one key, can't comp. sign the tx
         assert_equal(rawTxPartialSigned1['complete'], False)
 
         rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(
             rawTx2, inputs)
         self.log.debug(rawTxPartialSigned2)
         # node2 only has one key, can't comp. sign the tx
         assert_equal(rawTxPartialSigned2['complete'], False)
         rawTxComb = self.nodes[2].combinerawtransaction(
             [rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
         self.log.debug(rawTxComb)
         self.nodes[2].sendrawtransaction(rawTxComb)
         rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
         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
         txId = rawTx["txid"]
         assert_equal(
             self.nodes[0].getrawtransaction(txId), rawTxSigned['hex'])
 
         # 2. valid parameters - supply txid and 0 for non-verbose
         assert_equal(
             self.nodes[0].getrawtransaction(txId, 0), rawTxSigned['hex'])
 
         # 3. valid parameters - supply txid and False for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(txId, 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(txId, 1)["hex"],
                      rawTxSigned['hex'])
 
         # 5. valid parameters - supply txid and True for non-verbose
         assert_equal(self.nodes[0].getrawtransaction(txId, True)["hex"],
                      rawTxSigned['hex'])
 
         # 6. invalid parameters - supply txid and string "Flase"
         assert_raises_rpc_error(-1, "not a boolean",
                                 self.nodes[0].getrawtransaction,
                                 txId, "Flase")
 
         # 7. invalid parameters - supply txid and empty array
         assert_raises_rpc_error(-1, "not a boolean",
                                 self.nodes[0].getrawtransaction, txId, [])
 
         # 8. invalid parameters - supply txid and empty dict
         assert_raises_rpc_error(
             -1, "not a boolean", self.nodes[0].getrawtransaction, txId, {})
 
         # Sanity checks on verbose getrawtransaction output
         rawTxOutput = self.nodes[0].getrawtransaction(txId, True)
         assert_equal(rawTxOutput["hex"], rawTxSigned["hex"])
         assert_equal(rawTxOutput["txid"], txId)
         assert_equal(rawTxOutput["hash"], txId)
         assert_greater_than(rawTxOutput["size"], 300)
         assert_equal(rawTxOutput["version"], 0x02)
         assert_equal(rawTxOutput["locktime"], 0)
         assert_equal(len(rawTxOutput["vin"]), 1)
         assert_equal(len(rawTxOutput["vout"]), 1)
         assert_equal(rawTxOutput["blockhash"], rawTxBlock["hash"])
         assert_equal(rawTxOutput["confirmations"], 3)
         assert_equal(rawTxOutput["time"], rawTxBlock["time"])
         assert_equal(rawTxOutput["blocktime"], rawTxBlock["time"])
 
         inputs = [
             {'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[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[0]['sequence'] = 4294967296
         assert_raises_rpc_error(
             -8, 'Invalid parameter, sequence number is out of range',
             self.nodes[0].createrawtransaction, inputs, outputs)
 
         inputs[0]['sequence'] = 4294967294
         rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
 
         ####################################
         # TRANSACTION VERSION NUMBER TESTS #
         ####################################
 
         # Test the minimum transaction version number that fits in a signed
         # 32-bit integer.
         tx = CTransaction()
         tx.nVersion = -0x80000000
         rawtx = ToHex(tx)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['version'], -0x80000000)
 
         # Test the maximum transaction version number that fits in a signed
         # 32-bit integer.
         tx = CTransaction()
         tx.nVersion = 0x7fffffff
         rawtx = ToHex(tx)
         decrawtx = self.nodes[0].decoderawtransaction(rawtx)
         assert_equal(decrawtx['version'], 0x7fffffff)
 
         self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate')
 
         # Test a transaction with a small fee.
         txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
         rawTx = self.nodes[0].getrawtransaction(txId, True)
         vout = next(o for o in rawTx['vout']
                     if o['value'] == Decimal('1.00000000'))
 
         self.sync_all()
         inputs = [{"txid": txId, "vout": vout['n']}]
         # Fee 10,000 satoshis, (1 - (10000 sat * 0.00000001 BCH/sat)) = 0.9999
         outputs = {self.nodes[0].getnewaddress(): Decimal("0.99990000")}
         rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx)
         assert_equal(rawTxSigned['complete'], True)
         # Fee 10,000 satoshis, ~200 b transaction, fee rate should land around 50 sat/byte = 0.00050000 BCH/kB
         # Thus, testmempoolaccept should reject
         testres = self.nodes[2].testmempoolaccept(
             [rawTxSigned['hex']], 0.00050000)[0]
         assert_equal(testres['allowed'], False)
-        assert_equal(testres['reject-reason'], '256: absurdly-high-fee')
+        assert_equal(testres['reject-reason'], 'absurdly-high-fee')
         # and sendrawtransaction should throw
         assert_raises_rpc_error(-26,
                                 "absurdly-high-fee",
                                 self.nodes[2].sendrawtransaction,
                                 rawTxSigned['hex'],
                                 0.00001000)
         # and the following calls should both succeed
         testres = self.nodes[2].testmempoolaccept(
             rawtxs=[rawTxSigned['hex']])[0]
         assert_equal(testres['allowed'], True)
         self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'])
 
         # Test a transaction with a large fee.
         txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
         rawTx = self.nodes[0].getrawtransaction(txId, True)
         vout = next(o for o in rawTx['vout']
                     if o['value'] == Decimal('1.00000000'))
 
         self.sync_all()
         inputs = [{"txid": txId, "vout": vout['n']}]
         # Fee 2,000,000 satoshis, (1 - (2000000 sat * 0.00000001 BCH/sat)) =
         # 0.98
         outputs = {self.nodes[0].getnewaddress(): Decimal("0.98000000")}
         rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
         rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx)
         assert_equal(rawTxSigned['complete'], True)
         # Fee 2,000,000 satoshis, ~100 b transaction, fee rate should land around 20,000 sat/byte = 0.20000000 BCH/kB
         # Thus, testmempoolaccept should reject
         testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']])[0]
         assert_equal(testres['allowed'], False)
-        assert_equal(testres['reject-reason'], '256: absurdly-high-fee')
+        assert_equal(testres['reject-reason'], 'absurdly-high-fee')
         # and sendrawtransaction should throw
         assert_raises_rpc_error(-26,
                                 "absurdly-high-fee",
                                 self.nodes[2].sendrawtransaction,
                                 rawTxSigned['hex'])
         # and the following calls should both succeed
         testres = self.nodes[2].testmempoolaccept(
             rawtxs=[rawTxSigned['hex']], maxfeerate='0.20000000')[0]
         assert_equal(testres['allowed'], True)
         self.nodes[2].sendrawtransaction(
             hexstring=rawTxSigned['hex'],
             maxfeerate='0.20000000')
 
         ##########################################
         # Decoding weird scripts in transactions #
         ##########################################
 
         self.log.info('Decode correctly-formatted but weird transactions')
         tx = CTransaction()
         # empty
         self.nodes[0].decoderawtransaction(ToHex(tx))
         # truncated push
         tx.vin.append(CTxIn(COutPoint(42, 0), b'\x4e\x00\x00'))
         tx.vin.append(CTxIn(COutPoint(42, 0), b'\x4c\x10TRUNC'))
         tx.vout.append(CTxOut(0, b'\x4e\x00\x00'))
         tx.vout.append(CTxOut(0, b'\x4c\x10TRUNC'))
         self.nodes[0].decoderawtransaction(ToHex(tx))
         # giant pushes and long scripts
         tx.vin.append(
             CTxIn(COutPoint(42, 0), CScript([b'giant push' * 10000])))
         tx.vout.append(CTxOut(0, CScript([b'giant push' * 10000])))
         self.nodes[0].decoderawtransaction(ToHex(tx))
 
         self.log.info('Refuse garbage after transaction')
         assert_raises_rpc_error(-22, 'TX decode failed',
                                 self.nodes[0].decoderawtransaction, ToHex(tx) + '00')
 
 
 if __name__ == '__main__':
     RawTransactionsTest().main()