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 : }
|