LCOV - code coverage report
Current view: top level - src - core_write.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 181 187 96.8 %
Date: 2022-04-21 14:51:19 Functions: 7 7 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 72 82 87.8 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2021 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/amount.h>
#       8                 :            : #include <consensus/consensus.h>
#       9                 :            : #include <consensus/validation.h>
#      10                 :            : #include <key_io.h>
#      11                 :            : #include <script/descriptor.h>
#      12                 :            : #include <script/script.h>
#      13                 :            : #include <script/standard.h>
#      14                 :            : #include <serialize.h>
#      15                 :            : #include <streams.h>
#      16                 :            : #include <undo.h>
#      17                 :            : #include <univalue.h>
#      18                 :            : #include <util/check.h>
#      19                 :            : #include <util/strencodings.h>
#      20                 :            : #include <util/system.h>
#      21                 :            : 
#      22                 :            : #include <map>
#      23                 :            : #include <string>
#      24                 :            : #include <vector>
#      25                 :            : 
#      26                 :            : UniValue ValueFromAmount(const CAmount amount)
#      27                 :      93455 : {
#      28                 :      93455 :     static_assert(COIN > 1);
#      29                 :      93455 :     int64_t quotient = amount / COIN;
#      30                 :      93455 :     int64_t remainder = amount % COIN;
#      31         [ +  + ]:      93455 :     if (amount < 0) {
#      32                 :       2395 :         quotient = -quotient;
#      33                 :       2395 :         remainder = -remainder;
#      34                 :       2395 :     }
#      35                 :      93455 :     return UniValue(UniValue::VNUM,
#      36         [ +  + ]:      93455 :             strprintf("%s%d.%08d", amount < 0 ? "-" : "", quotient, remainder));
#      37                 :      93455 : }
#      38                 :            : 
#      39                 :            : std::string FormatScript(const CScript& script)
#      40                 :        536 : {
#      41                 :        536 :     std::string ret;
#      42                 :        536 :     CScript::const_iterator it = script.begin();
#      43                 :        536 :     opcodetype op;
#      44         [ +  + ]:       1734 :     while (it != script.end()) {
#      45                 :       1198 :         CScript::const_iterator it2 = it;
#      46                 :       1198 :         std::vector<unsigned char> vch;
#      47         [ +  - ]:       1198 :         if (script.GetOp(it, op, vch)) {
#      48         [ +  + ]:       1198 :             if (op == OP_0) {
#      49                 :        126 :                 ret += "0 ";
#      50                 :        126 :                 continue;
#      51 [ +  + ][ +  + ]:       1072 :             } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
#                 [ -  + ]
#      52                 :        126 :                 ret += strprintf("%i ", op - OP_1NEGATE - 1);
#      53                 :        126 :                 continue;
#      54 [ +  + ][ +  - ]:        946 :             } else if (op >= OP_NOP && op <= OP_NOP10) {
#      55                 :        356 :                 std::string str(GetOpName(op));
#      56         [ +  - ]:        356 :                 if (str.substr(0, 3) == std::string("OP_")) {
#      57                 :        356 :                     ret += str.substr(3, std::string::npos) + " ";
#      58                 :        356 :                     continue;
#      59                 :        356 :                 }
#      60                 :        356 :             }
#      61         [ +  - ]:        590 :             if (vch.size() > 0) {
#      62                 :        590 :                 ret += strprintf("0x%x 0x%x ", HexStr(std::vector<uint8_t>(it2, it - vch.size())),
#      63                 :        590 :                                                HexStr(std::vector<uint8_t>(it - vch.size(), it)));
#      64                 :        590 :             } else {
#      65                 :          0 :                 ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, it)));
#      66                 :          0 :             }
#      67                 :        590 :             continue;
#      68                 :       1198 :         }
#      69                 :          0 :         ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
#      70                 :          0 :         break;
#      71                 :       1198 :     }
#      72         [ +  + ]:        536 :     return ret.substr(0, ret.empty() ? ret.npos : ret.size() - 1);
#      73                 :        536 : }
#      74                 :            : 
#      75                 :            : const std::map<unsigned char, std::string> mapSigHashTypes = {
#      76                 :            :     {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")},
#      77                 :            :     {static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")},
#      78                 :            :     {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")},
#      79                 :            :     {static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")},
#      80                 :            :     {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")},
#      81                 :            :     {static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")},
#      82                 :            : };
#      83                 :            : 
#      84                 :            : std::string SighashToStr(unsigned char sighash_type)
#      85                 :          2 : {
#      86                 :          2 :     const auto& it = mapSigHashTypes.find(sighash_type);
#      87         [ -  + ]:          2 :     if (it == mapSigHashTypes.end()) return "";
#      88                 :          2 :     return it->second;
#      89                 :          2 : }
#      90                 :            : 
#      91                 :            : /**
#      92                 :            :  * Create the assembly string representation of a CScript object.
#      93                 :            :  * @param[in] script    CScript object to convert into the asm string representation.
#      94                 :            :  * @param[in] fAttemptSighashDecode    Whether to attempt to decode sighash types on data within the script that matches the format
#      95                 :            :  *                                     of a signature. Only pass true for scripts you believe could contain signatures. For example,
#      96                 :            :  *                                     pass false, or omit the this argument (defaults to false), for scriptPubKeys.
#      97                 :            :  */
#      98                 :            : std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
#      99                 :      31624 : {
#     100                 :      31624 :     std::string str;
#     101                 :      31624 :     opcodetype opcode;
#     102                 :      31624 :     std::vector<unsigned char> vch;
#     103                 :      31624 :     CScript::const_iterator pc = script.begin();
#     104         [ +  + ]:    3454011 :     while (pc < script.end()) {
#     105         [ +  + ]:    3422392 :         if (!str.empty()) {
#     106                 :    3393143 :             str += " ";
#     107                 :    3393143 :         }
#     108         [ +  + ]:    3422392 :         if (!script.GetOp(pc, opcode, vch)) {
#     109                 :          5 :             str += "[error]";
#     110                 :          5 :             return str;
#     111                 :          5 :         }
#     112 [ +  - ][ +  + ]:    3422387 :         if (0 <= opcode && opcode <= OP_PUSHDATA4) {
#     113         [ +  + ]:    3399805 :             if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
#     114                 :    3381825 :                 str += strprintf("%d", CScriptNum(vch, false).getint());
#     115                 :    3381825 :             } else {
#     116                 :            :                 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
#     117 [ +  + ][ +  + ]:      17980 :                 if (fAttemptSighashDecode && !script.IsUnspendable()) {
#     118                 :       3950 :                     std::string strSigHashDecode;
#     119                 :            :                     // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
#     120                 :            :                     // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
#     121                 :            :                     // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
#     122                 :            :                     // checks in CheckSignatureEncoding.
#     123         [ +  + ]:       3950 :                     if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, nullptr)) {
#     124                 :       1927 :                         const unsigned char chSigHashType = vch.back();
#     125                 :       1927 :                         const auto it = mapSigHashTypes.find(chSigHashType);
#     126         [ +  - ]:       1927 :                         if (it != mapSigHashTypes.end()) {
#     127                 :       1927 :                             strSigHashDecode = "[" + it->second + "]";
#     128                 :       1927 :                             vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
#     129                 :       1927 :                         }
#     130                 :       1927 :                     }
#     131                 :       3950 :                     str += HexStr(vch) + strSigHashDecode;
#     132                 :      14030 :                 } else {
#     133                 :      14030 :                     str += HexStr(vch);
#     134                 :      14030 :                 }
#     135                 :      17980 :             }
#     136                 :    3399805 :         } else {
#     137                 :      22582 :             str += GetOpName(opcode);
#     138                 :      22582 :         }
#     139                 :    3422387 :     }
#     140                 :      31619 :     return str;
#     141                 :      31624 : }
#     142                 :            : 
#     143                 :            : std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
#     144                 :       5993 : {
#     145                 :       5993 :     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags);
#     146                 :       5993 :     ssTx << tx;
#     147                 :       5993 :     return HexStr(ssTx);
#     148                 :       5993 : }
#     149                 :            : 
#     150                 :            : void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address)
#     151                 :      27125 : {
#     152                 :      27125 :     CTxDestination address;
#     153                 :            : 
#     154                 :      27125 :     out.pushKV("asm", ScriptToAsmStr(script));
#     155         [ +  + ]:      27125 :     if (include_address) {
#     156                 :      26947 :         out.pushKV("desc", InferDescriptor(script, DUMMY_SIGNING_PROVIDER)->ToString());
#     157                 :      26947 :     }
#     158         [ +  + ]:      27125 :     if (include_hex) {
#     159                 :      27097 :         out.pushKV("hex", HexStr(script));
#     160                 :      27097 :     }
#     161                 :            : 
#     162                 :      27125 :     std::vector<std::vector<unsigned char>> solns;
#     163                 :      27125 :     const TxoutType type{Solver(script, solns)};
#     164                 :            : 
#     165 [ +  + ][ +  + ]:      27125 :     if (include_address && ExtractDestination(script, address) && type != TxoutType::PUBKEY) {
#                 [ +  + ]
#     166                 :      11641 :         out.pushKV("address", EncodeDestination(address));
#     167                 :      11641 :     }
#     168                 :      27125 :     out.pushKV("type", GetTxnOutputType(type));
#     169                 :      27125 : }
#     170                 :            : 
#     171                 :            : void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo, TxVerbosity verbosity)
#     172                 :       3568 : {
#     173                 :       3568 :     entry.pushKV("txid", tx.GetHash().GetHex());
#     174                 :       3568 :     entry.pushKV("hash", tx.GetWitnessHash().GetHex());
#     175                 :            :     // Transaction version is actually unsigned in consensus checks, just signed in memory,
#     176                 :            :     // so cast to unsigned before giving it to the user.
#     177                 :       3568 :     entry.pushKV("version", static_cast<int64_t>(static_cast<uint32_t>(tx.nVersion)));
#     178                 :       3568 :     entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
#     179                 :       3568 :     entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
#     180                 :       3568 :     entry.pushKV("weight", GetTransactionWeight(tx));
#     181                 :       3568 :     entry.pushKV("locktime", (int64_t)tx.nLockTime);
#     182                 :            : 
#     183                 :       3568 :     UniValue vin{UniValue::VARR};
#     184                 :            : 
#     185                 :            :     // If available, use Undo data to calculate the fee. Note that txundo == nullptr
#     186                 :            :     // for coinbase transactions and for transactions where undo data is unavailable.
#     187                 :       3568 :     const bool have_undo = txundo != nullptr;
#     188                 :       3568 :     CAmount amt_total_in = 0;
#     189                 :       3568 :     CAmount amt_total_out = 0;
#     190                 :            : 
#     191         [ +  + ]:       9695 :     for (unsigned int i = 0; i < tx.vin.size(); i++) {
#     192                 :       6127 :         const CTxIn& txin = tx.vin[i];
#     193                 :       6127 :         UniValue in(UniValue::VOBJ);
#     194         [ +  + ]:       6127 :         if (tx.IsCoinBase()) {
#     195                 :       1701 :             in.pushKV("coinbase", HexStr(txin.scriptSig));
#     196                 :       4426 :         } else {
#     197                 :       4426 :             in.pushKV("txid", txin.prevout.hash.GetHex());
#     198                 :       4426 :             in.pushKV("vout", (int64_t)txin.prevout.n);
#     199                 :       4426 :             UniValue o(UniValue::VOBJ);
#     200                 :       4426 :             o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
#     201                 :       4426 :             o.pushKV("hex", HexStr(txin.scriptSig));
#     202                 :       4426 :             in.pushKV("scriptSig", o);
#     203                 :       4426 :         }
#     204         [ +  + ]:       6127 :         if (!tx.vin[i].scriptWitness.IsNull()) {
#     205                 :       3593 :             UniValue txinwitness(UniValue::VARR);
#     206         [ +  + ]:       5560 :             for (const auto& item : tx.vin[i].scriptWitness.stack) {
#     207                 :       5560 :                 txinwitness.push_back(HexStr(item));
#     208                 :       5560 :             }
#     209                 :       3593 :             in.pushKV("txinwitness", txinwitness);
#     210                 :       3593 :         }
#     211         [ +  + ]:       6127 :         if (have_undo) {
#     212                 :         11 :             const Coin& prev_coin = txundo->vprevout[i];
#     213                 :         11 :             const CTxOut& prev_txout = prev_coin.out;
#     214                 :            : 
#     215                 :         11 :             amt_total_in += prev_txout.nValue;
#     216                 :            : 
#     217         [ +  + ]:         11 :             if (verbosity == TxVerbosity::SHOW_DETAILS_AND_PREVOUT) {
#     218                 :          5 :                 UniValue o_script_pub_key(UniValue::VOBJ);
#     219                 :          5 :                 ScriptToUniv(prev_txout.scriptPubKey, /*out=*/o_script_pub_key, /*include_hex=*/true, /*include_address=*/true);
#     220                 :            : 
#     221                 :          5 :                 UniValue p(UniValue::VOBJ);
#     222                 :          5 :                 p.pushKV("generated", bool(prev_coin.fCoinBase));
#     223                 :          5 :                 p.pushKV("height", uint64_t(prev_coin.nHeight));
#     224                 :          5 :                 p.pushKV("value", ValueFromAmount(prev_txout.nValue));
#     225                 :          5 :                 p.pushKV("scriptPubKey", o_script_pub_key);
#     226                 :          5 :                 in.pushKV("prevout", p);
#     227                 :          5 :             }
#     228                 :         11 :         }
#     229                 :       6127 :         in.pushKV("sequence", (int64_t)txin.nSequence);
#     230                 :       6127 :         vin.push_back(in);
#     231                 :       6127 :     }
#     232                 :       3568 :     entry.pushKV("vin", vin);
#     233                 :            : 
#     234                 :       3568 :     UniValue vout(UniValue::VARR);
#     235         [ +  + ]:      25365 :     for (unsigned int i = 0; i < tx.vout.size(); i++) {
#     236                 :      21797 :         const CTxOut& txout = tx.vout[i];
#     237                 :            : 
#     238                 :      21797 :         UniValue out(UniValue::VOBJ);
#     239                 :            : 
#     240                 :      21797 :         out.pushKV("value", ValueFromAmount(txout.nValue));
#     241                 :      21797 :         out.pushKV("n", (int64_t)i);
#     242                 :            : 
#     243                 :      21797 :         UniValue o(UniValue::VOBJ);
#     244                 :      21797 :         ScriptToUniv(txout.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);
#     245                 :      21797 :         out.pushKV("scriptPubKey", o);
#     246                 :      21797 :         vout.push_back(out);
#     247                 :            : 
#     248         [ +  + ]:      21797 :         if (have_undo) {
#     249                 :         12 :             amt_total_out += txout.nValue;
#     250                 :         12 :         }
#     251                 :      21797 :     }
#     252                 :       3568 :     entry.pushKV("vout", vout);
#     253                 :            : 
#     254         [ +  + ]:       3568 :     if (have_undo) {
#     255                 :         11 :         const CAmount fee = amt_total_in - amt_total_out;
#     256         [ -  + ]:         11 :         CHECK_NONFATAL(MoneyRange(fee));
#     257                 :         11 :         entry.pushKV("fee", ValueFromAmount(fee));
#     258                 :         11 :     }
#     259                 :            : 
#     260         [ -  + ]:       3568 :     if (!block_hash.IsNull()) {
#     261                 :          0 :         entry.pushKV("blockhash", block_hash.GetHex());
#     262                 :          0 :     }
#     263                 :            : 
#     264         [ +  + ]:       3568 :     if (include_hex) {
#     265                 :       2044 :         entry.pushKV("hex", EncodeHexTx(tx, serialize_flags)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
#     266                 :       2044 :     }
#     267                 :       3568 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a