LCOV - code coverage report
Current view: top level - src - core_write.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 189 195 96.9 %
Date: 2021-06-29 14:35:33 Functions: 8 8 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: 74 86 86.0 %

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

Generated by: LCOV version 1.14