LCOV - code coverage report
Current view: top level - src - core_write.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 158 164 96.3 %
Date: 2020-09-26 01:30:44 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2019 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <core_io.h>
       6             : 
       7             : #include <consensus/consensus.h>
       8             : #include <consensus/validation.h>
       9             : #include <key_io.h>
      10             : #include <script/script.h>
      11             : #include <script/standard.h>
      12             : #include <serialize.h>
      13             : #include <streams.h>
      14             : #include <univalue.h>
      15             : #include <util/system.h>
      16             : #include <util/strencodings.h>
      17             : 
      18      415616 : UniValue ValueFromAmount(const CAmount& amount)
      19             : {
      20      415616 :     bool sign = amount < 0;
      21      415616 :     int64_t n_abs = (sign ? -amount : amount);
      22      415616 :     int64_t quotient = n_abs / COIN;
      23      415616 :     int64_t remainder = n_abs % COIN;
      24      415616 :     return UniValue(UniValue::VNUM,
      25      415616 :             strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder));
      26      415616 : }
      27             : 
      28         268 : std::string FormatScript(const CScript& script)
      29             : {
      30         268 :     std::string ret;
      31         268 :     CScript::const_iterator it = script.begin();
      32         268 :     opcodetype op;
      33         867 :     while (it != script.end()) {
      34         599 :         CScript::const_iterator it2 = it;
      35         599 :         std::vector<unsigned char> vch;
      36         599 :         if (script.GetOp(it, op, vch)) {
      37         599 :             if (op == OP_0) {
      38          63 :                 ret += "0 ";
      39          63 :                 continue;
      40         536 :             } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
      41          63 :                 ret += strprintf("%i ", op - OP_1NEGATE - 1);
      42          63 :                 continue;
      43         473 :             } else if (op >= OP_NOP && op <= OP_NOP10) {
      44         178 :                 std::string str(GetOpName(op));
      45         178 :                 if (str.substr(0, 3) == std::string("OP_")) {
      46         178 :                     ret += str.substr(3, std::string::npos) + " ";
      47         178 :                     continue;
      48             :                 }
      49         178 :             }
      50         295 :             if (vch.size() > 0) {
      51         590 :                 ret += strprintf("0x%x 0x%x ", HexStr(std::vector<uint8_t>(it2, it - vch.size())),
      52         295 :                                                HexStr(std::vector<uint8_t>(it - vch.size(), it)));
      53         295 :             } else {
      54           0 :                 ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, it)));
      55             :             }
      56         295 :             continue;
      57             :         }
      58           0 :         ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
      59           0 :         break;
      60         599 :     }
      61         268 :     return ret.substr(0, ret.size() - 1);
      62         268 : }
      63             : 
      64        4386 : const std::map<unsigned char, std::string> mapSigHashTypes = {
      65         731 :     {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")},
      66         731 :     {static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")},
      67         731 :     {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")},
      68         731 :     {static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")},
      69         731 :     {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")},
      70         731 :     {static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")},
      71             : };
      72             : 
      73           2 : std::string SighashToStr(unsigned char sighash_type)
      74             : {
      75           2 :     const auto& it = mapSigHashTypes.find(sighash_type);
      76           2 :     if (it == mapSigHashTypes.end()) return "";
      77           2 :     return it->second;
      78           2 : }
      79             : 
      80             : /**
      81             :  * Create the assembly string representation of a CScript object.
      82             :  * @param[in] script    CScript object to convert into the asm string representation.
      83             :  * @param[in] fAttemptSighashDecode    Whether to attempt to decode sighash types on data within the script that matches the format
      84             :  *                                     of a signature. Only pass true for scripts you believe could contain signatures. For example,
      85             :  *                                     pass false, or omit the this argument (defaults to false), for scriptPubKeys.
      86             :  */
      87      101885 : std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
      88             : {
      89      101885 :     std::string str;
      90      101885 :     opcodetype opcode;
      91      101885 :     std::vector<unsigned char> vch;
      92      101885 :     CScript::const_iterator pc = script.begin();
      93      427498 :     while (pc < script.end()) {
      94      325613 :         if (!str.empty()) {
      95      224431 :             str += " ";
      96             :         }
      97      325613 :         if (!script.GetOp(pc, opcode, vch)) {
      98           0 :             str += "[error]";
      99           0 :             return str;
     100             :         }
     101      325613 :         if (0 <= opcode && opcode <= OP_PUSHDATA4) {
     102      182800 :             if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
     103       16472 :                 str += strprintf("%d", CScriptNum(vch, false).getint());
     104       16472 :             } else {
     105             :                 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
     106      166328 :                 if (fAttemptSighashDecode && !script.IsUnspendable()) {
     107      120033 :                     std::string strSigHashDecode;
     108             :                     // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
     109             :                     // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
     110             :                     // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
     111             :                     // checks in CheckSignatureEncoding.
     112      120033 :                     if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, nullptr)) {
     113       65078 :                         const unsigned char chSigHashType = vch.back();
     114       65078 :                         const auto it = mapSigHashTypes.find(chSigHashType);
     115       65078 :                         if (it != mapSigHashTypes.end()) {
     116       65078 :                             strSigHashDecode = "[" + it->second + "]";
     117       65078 :                             vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
     118       65078 :                         }
     119       65078 :                     }
     120      120033 :                     str += HexStr(vch) + strSigHashDecode;
     121      120033 :                 } else {
     122       46295 :                     str += HexStr(vch);
     123             :                 }
     124             :             }
     125             :         } else {
     126      142813 :             str += GetOpName(opcode);
     127             :         }
     128             :     }
     129      101885 :     return str;
     130      101885 : }
     131             : 
     132       21002 : std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
     133             : {
     134       21002 :     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags);
     135       21002 :     ssTx << tx;
     136       21002 :     return HexStr(ssTx);
     137       21002 : }
     138             : 
     139         228 : void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
     140             : {
     141         228 :     out.pushKV("asm", ScriptToAsmStr(script));
     142         228 :     out.pushKV("hex", HexStr(script));
     143             : 
     144         228 :     std::vector<std::vector<unsigned char>> solns;
     145         228 :     TxoutType type = Solver(script, solns);
     146         228 :     out.pushKV("type", GetTxnOutputType(type));
     147             : 
     148         228 :     CTxDestination address;
     149         228 :     if (include_address && ExtractDestination(script, address) && type != TxoutType::PUBKEY) {
     150          92 :         out.pushKV("address", EncodeDestination(address));
     151          92 :     }
     152         228 : }
     153             : 
     154       45987 : void ScriptPubKeyToUniv(const CScript& scriptPubKey,
     155             :                         UniValue& out, bool fIncludeHex)
     156             : {
     157       45987 :     TxoutType type;
     158       45987 :     std::vector<CTxDestination> addresses;
     159       45987 :     int nRequired;
     160             : 
     161       45987 :     out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
     162       45987 :     if (fIncludeHex)
     163       45966 :         out.pushKV("hex", HexStr(scriptPubKey));
     164             : 
     165       45987 :     if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired) || type == TxoutType::PUBKEY) {
     166          93 :         out.pushKV("type", GetTxnOutputType(type));
     167          93 :         return;
     168             :     }
     169             : 
     170       45894 :     out.pushKV("reqSigs", nRequired);
     171       45894 :     out.pushKV("type", GetTxnOutputType(type));
     172             : 
     173       45894 :     UniValue a(UniValue::VARR);
     174       91793 :     for (const CTxDestination& addr : addresses) {
     175       45899 :         a.push_back(EncodeDestination(addr));
     176             :     }
     177       45894 :     out.pushKV("addresses", a);
     178       45987 : }
     179             : 
     180       17827 : void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
     181             : {
     182       17827 :     entry.pushKV("txid", tx.GetHash().GetHex());
     183       17827 :     entry.pushKV("hash", tx.GetWitnessHash().GetHex());
     184             :     // Transaction version is actually unsigned in consensus checks, just signed in memory,
     185             :     // so cast to unsigned before giving it to the user.
     186       17827 :     entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
     187       17827 :     entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
     188       17827 :     entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
     189       17827 :     entry.pushKV("weight", GetTransactionWeight(tx));
     190       17827 :     entry.pushKV("locktime", (int64_t)tx.nLockTime);
     191             : 
     192       17827 :     UniValue vin(UniValue::VARR);
     193       73511 :     for (unsigned int i = 0; i < tx.vin.size(); i++) {
     194       55684 :         const CTxIn& txin = tx.vin[i];
     195       55684 :         UniValue in(UniValue::VOBJ);
     196       55684 :         if (tx.IsCoinBase())
     197          48 :             in.pushKV("coinbase", HexStr(txin.scriptSig));
     198             :         else {
     199       55636 :             in.pushKV("txid", txin.prevout.hash.GetHex());
     200       55636 :             in.pushKV("vout", (int64_t)txin.prevout.n);
     201       55636 :             UniValue o(UniValue::VOBJ);
     202       55636 :             o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
     203       55636 :             o.pushKV("hex", HexStr(txin.scriptSig));
     204       55636 :             in.pushKV("scriptSig", o);
     205       55636 :         }
     206       55684 :         if (!tx.vin[i].scriptWitness.IsNull()) {
     207         430 :             UniValue txinwitness(UniValue::VARR);
     208        1315 :             for (const auto& item : tx.vin[i].scriptWitness.stack) {
     209         885 :                 txinwitness.push_back(HexStr(item));
     210             :             }
     211         430 :             in.pushKV("txinwitness", txinwitness);
     212         430 :         }
     213       55684 :         in.pushKV("sequence", (int64_t)txin.nSequence);
     214       55684 :         vin.push_back(in);
     215       55684 :     }
     216       17827 :     entry.pushKV("vin", vin);
     217             : 
     218       17827 :     UniValue vout(UniValue::VARR);
     219       58811 :     for (unsigned int i = 0; i < tx.vout.size(); i++) {
     220       40984 :         const CTxOut& txout = tx.vout[i];
     221             : 
     222       40984 :         UniValue out(UniValue::VOBJ);
     223             : 
     224       40984 :         out.pushKV("value", ValueFromAmount(txout.nValue));
     225       40984 :         out.pushKV("n", (int64_t)i);
     226             : 
     227       40984 :         UniValue o(UniValue::VOBJ);
     228       40984 :         ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
     229       40984 :         out.pushKV("scriptPubKey", o);
     230       40984 :         vout.push_back(out);
     231       40984 :     }
     232       17827 :     entry.pushKV("vout", vout);
     233             : 
     234       17827 :     if (!hashBlock.IsNull())
     235           0 :         entry.pushKV("blockhash", hashBlock.GetHex());
     236             : 
     237       17827 :     if (include_hex) {
     238       17463 :         entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
     239       17463 :     }
     240       17827 : }

Generated by: LCOV version 1.15