LCOV - code coverage report
Current view: top level - src - core_write.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 113 118 95.8 %
Date: 2025-02-23 09:33:43 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2014 The Bitcoin developers
       2             : // Copyright (c) 2017-2021 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "core_io.h"
       7             : 
       8             : #include "key_io.h"
       9             : #include "primitives/transaction.h"
      10             : #include "script/script.h"
      11             : #include "script/standard.h"
      12             : #include "sapling/sapling_core_write.h"
      13             : #include "serialize.h"
      14             : #include "streams.h"
      15             : #include <univalue.h>
      16             : #include "util/system.h"
      17             : #include "utilmoneystr.h"
      18             : #include "utilstrencodings.h"
      19             : 
      20         164 : std::string FormatScript(const CScript& script)
      21             : {
      22         164 :     std::string ret;
      23         328 :     CScript::const_iterator it = script.begin();
      24         610 :     opcodetype op;
      25        1220 :     while (it != script.end()) {
      26         446 :         CScript::const_iterator it2 = it;
      27         446 :         std::vector<unsigned char> vch;
      28         446 :         if (script.GetOp2(it, op, &vch)) {
      29         446 :             if (op == OP_0) {
      30          36 :                 ret += "0 ";
      31         482 :                 continue;
      32         410 :             } else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
      33         120 :                 ret += strprintf("%i ", op - OP_1NEGATE - 1);
      34          60 :                 continue;
      35         350 :             } else if (op >= OP_NOP && op <= OP_NOP10) {
      36         131 :                 std::string str(GetOpName(op));
      37         131 :                 if (str.substr(0, 3) == std::string("OP_")) {
      38         262 :                     ret += str.substr(3, std::string::npos) + " ";
      39         155 :                     continue;
      40             :                 }
      41             :             }
      42         219 :             if (vch.size() > 0) {
      43         876 :                 ret += strprintf("0x%x 0x%x ", HexStr(std::vector<uint8_t>(it2, it - vch.size())),
      44         876 :                                  HexStr(std::vector<uint8_t>(it - vch.size(), it)));
      45             :             } else {
      46           0 :                 ret += strprintf("0x%x", HexStr(std::vector<uint8_t>(it2, it)));
      47             :             }
      48         219 :             continue;
      49             :         }
      50           0 :         ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
      51           0 :         break;
      52             :     }
      53         328 :     return ret.substr(0, ret.size() - 1);
      54             : }
      55             : 
      56             : const std::map<unsigned char, std::string> mapSigHashTypes = {
      57             :     {static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL")},
      58             :     {static_cast<unsigned char>(SIGHASH_ALL | SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")},
      59             :     {static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE")},
      60             :     {static_cast<unsigned char>(SIGHASH_NONE | SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")},
      61             :     {static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE")},
      62             :     {static_cast<unsigned char>(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")}
      63             : };
      64             : 
      65             : /**
      66             :  * Create the assembly string representation of a CScript object.
      67             :  * @param[in] script    CScript object to convert into the asm string representation.
      68             :  * @param[in] fAttemptSighashDecode    Whether to attempt to decode sighash types on data within the script that matches the format
      69             :  *                                     of a signature. Only pass true for scripts you believe could contain signatures. For example,
      70             :  *                                     pass false, or omit the this argument (defaults to false), for scriptPubKeys.
      71             :  */
      72        2190 : std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
      73             : {
      74        2190 :     std::string str;
      75        2190 :     opcodetype opcode;
      76        4380 :     std::vector<unsigned char> vch;
      77        4380 :     CScript::const_iterator pc = script.begin();
      78       11419 :     while (pc < script.end()) {
      79        9229 :         if (!str.empty()) {
      80        7104 :             str += " ";
      81             :         }
      82        9229 :         if (!script.GetOp(pc, opcode, vch)) {
      83        2190 :             str += "[error]";
      84             :             return str;
      85             :         }
      86        9229 :         if (0 <= opcode && opcode <= OP_PUSHDATA4) {
      87        2749 :             if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
      88          69 :                 str += strprintf("%d", CScriptNum(vch, false).getint());
      89             :             } else {
      90             :                 // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
      91        2726 :                 if (fAttemptSighashDecode && !script.IsUnspendable()) {
      92        2174 :                     std::string strSigHashDecode;
      93             :                     // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
      94             :                     // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
      95             :                     // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
      96             :                     // checks in CheckSignatureEncoding.
      97        1087 :                     if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, nullptr)) {
      98         547 :                         const unsigned char chSigHashType = vch.back();
      99         547 :                         if (mapSigHashTypes.count(chSigHashType)) {
     100         547 :                             strSigHashDecode = "[" + mapSigHashTypes.find(chSigHashType)->second + "]";
     101         547 :                             vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode.
     102             :                         }
     103             :                     }
     104        3261 :                     str += HexStr(vch) + strSigHashDecode;
     105             :                 } else {
     106        4917 :                     str += HexStr(vch);
     107             :                 }
     108             :             }
     109             :         } else {
     110       17899 :             str += GetOpName(opcode);
     111             :         }
     112             :     }
     113             :     return str;
     114             : }
     115             : 
     116      106619 : std::string EncodeHexTx(const CTransaction& tx)
     117             : {
     118      106619 :     CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
     119      106619 :     ssTx << tx;
     120      106619 :     return HexStr(ssTx);
     121             : }
     122             : 
     123        1596 : void ScriptPubKeyToUniv(const CScript& scriptPubKey,
     124             :     UniValue& out,
     125             :     bool fIncludeHex)
     126             : {
     127        1596 :     txnouttype type;
     128        3155 :     std::vector<CTxDestination> addresses;
     129        1596 :     int nRequired;
     130             : 
     131        3192 :     out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
     132        1596 :     if (fIncludeHex)
     133        6314 :         out.pushKV("hex", HexStr(scriptPubKey));
     134             : 
     135        1596 :     if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
     136          42 :         if (!scriptPubKey.empty() && scriptPubKey.IsZerocoinMint()) {
     137           0 :             out.pushKV("type", "zerocoinmint"); // unsupported type.
     138             :         } else {
     139          74 :             out.pushKV("type", GetTxnOutputType(type));
     140             :         }
     141          37 :         return;
     142             :     }
     143             : 
     144        1559 :     out.pushKV("reqSigs", nRequired);
     145        1559 :     out.pushKV("type", GetTxnOutputType(type));
     146             : 
     147        1559 :     UniValue a(UniValue::VARR);
     148        1559 :     if (type == TX_COLDSTAKE && addresses.size() == 2) {
     149          52 :         a.push_back(EncodeDestination(addresses[0], CChainParams::STAKING_ADDRESS));
     150         104 :         a.push_back(EncodeDestination(addresses[1], CChainParams::PUBKEY_ADDRESS));
     151             :     } else {
     152        3016 :         for (const CTxDestination& addr : addresses)
     153        3018 :             a.push_back(EncodeDestination(addr));
     154             :     }
     155        3118 :     out.pushKV("addresses", a);
     156             : }
     157             : 
     158        1070 : static void SpecialTxToJSON(const CTransaction& tx, UniValue& entry)
     159             : {
     160        1070 :     if (tx.IsSpecialTx()) {
     161          77 :         entry.pushKV("extraPayloadSize", (int)tx.extraPayload->size());
     162         231 :         entry.pushKV("extraPayload", HexStr(*(tx.extraPayload)));
     163             :     }
     164        1070 : }
     165             : 
     166        1070 : void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
     167             : {
     168        2140 :     entry.pushKV("txid", tx.GetHash().GetHex());
     169        1070 :     entry.pushKV("version", tx.nVersion);
     170        1070 :     entry.pushKV("type", tx.nType);
     171        1070 :     entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
     172        1070 :     entry.pushKV("locktime", (int64_t)tx.nLockTime);
     173             : 
     174        2140 :     UniValue vin(UniValue::VARR);
     175        2311 :     for (const CTxIn& txin : tx.vin) {
     176        2482 :         UniValue in(UniValue::VOBJ);
     177        1241 :         if (tx.IsCoinBase())
     178        2001 :             in.pushKV("coinbase", HexStr(txin.scriptSig));
     179             :         else {
     180        1148 :             in.pushKV("txid", txin.prevout.hash.GetHex());
     181         574 :             in.pushKV("vout", (int64_t)txin.prevout.n);
     182         574 :             UniValue o(UniValue::VOBJ);
     183        1148 :             o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true));
     184        1722 :             o.pushKV("hex", HexStr(txin.scriptSig));
     185        1148 :             in.pushKV("scriptSig", o);
     186             :         }
     187        1241 :         in.pushKV("sequence", (int64_t)txin.nSequence);
     188        1241 :         vin.push_back(in);
     189             :     }
     190        1070 :     entry.pushKV("vin", vin);
     191             : 
     192        1070 :     UniValue vout(UniValue::VARR);
     193        2638 :     for (unsigned int i = 0; i < tx.vout.size(); i++) {
     194        1568 :         const CTxOut& txout = tx.vout[i];
     195             : 
     196        3136 :         UniValue out(UniValue::VOBJ);
     197             : 
     198        3136 :         UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue));
     199        1568 :         out.pushKV("value", outValue);
     200        1568 :         out.pushKV("n", (int64_t)i);
     201             : 
     202        3136 :         UniValue o(UniValue::VOBJ);
     203        1568 :         ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
     204        1568 :         out.pushKV("scriptPubKey", o);
     205        1568 :         vout.push_back(out);
     206             :     }
     207        1070 :     entry.pushKV("vout", vout);
     208             : 
     209             :     // Sapling
     210        1070 :     TxSaplingToJSON(tx, entry);
     211             : 
     212             :     // Special Txes
     213        1070 :     SpecialTxToJSON(tx, entry);
     214             : 
     215       35310 :     if (!hashBlock.IsNull())
     216           0 :         entry.pushKV("blockhash", hashBlock.GetHex());
     217             : 
     218        3210 :     entry.pushKV("hex", EncodeHexTx(tx)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".
     219        1070 : }

Generated by: LCOV version 1.14