Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <qt/transactiondesc.h>7#include <qt/bitcoinunits.h>8#include <qt/guiutil.h>9#include <qt/paymentserver.h>10#include <qt/transactionrecord.h>12#include <common/system.h>13#include <consensus/consensus.h>14#include <interfaces/node.h>15#include <interfaces/wallet.h>16#include <key_io.h>17#include <policy/policy.h>18#include <util/log.h>19#include <validation.h>21#include <cstdint>22#include <string>24#include <QLatin1String>26QString TransactionDesc::FormatTxStatus(const interfaces::WalletTxStatus& status, bool inMempool)27{28int depth = status.depth_in_main_chain;29if (depth < 0) {30/*: Text explaining the current status of a transaction, shown in the31status field of the details window for this transaction. This status32represents an unconfirmed transaction that conflicts with a confirmed33transaction. */34return tr("conflicted with a transaction with %1 confirmations").arg(-depth);35} else if (depth == 0) {36QString s;37if (inMempool) {38/*: Text explaining the current status of a transaction, shown in the39status field of the details window for this transaction. This status40represents an unconfirmed transaction that is in the memory pool. */41s = tr("0/unconfirmed, in memory pool");42} else {43/*: Text explaining the current status of a transaction, shown in the44status field of the details window for this transaction. This status45represents an unconfirmed transaction that is not in the memory pool. */46s = tr("0/unconfirmed, not in memory pool");47}48if (status.is_abandoned) {49/*: Text explaining the current status of a transaction, shown in the50status field of the details window for this transaction. This51status represents an abandoned transaction. */52s += QLatin1String(", ") + tr("abandoned");53}54return s;55} else if (depth < 6) {56/*: Text explaining the current status of a transaction, shown in the57status field of the details window for this transaction. This58status represents a transaction confirmed in at least one block,59but less than 6 blocks. */60return tr("%1/unconfirmed").arg(depth);61} else {62/*: Text explaining the current status of a transaction, shown in the63status field of the details window for this transaction. This status64represents a transaction confirmed in 6 or more blocks. */65return tr("%1 confirmations").arg(depth);66}67}69// Takes an encoded PaymentRequest as a string and tries to find the Common Name of the X.509 certificate70// used to sign the PaymentRequest.71bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)72{73// Search for the supported pki type strings74if (pr.find(std::string({0x12, 0x0b}) + "x509+sha256") != std::string::npos || pr.find(std::string({0x12, 0x09}) + "x509+sha1") != std::string::npos) {75// We want the common name of the Subject of the cert. This should be the second occurrence76// of the bytes 0x0603550403. The first occurrence of those is the common name of the issuer.77// After those bytes will be either 0x13 or 0x0C, then length, then either the ascii or utf878// string with the common name which is the merchant name79size_t cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03});80if (cn_pos != std::string::npos) {81cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03}, cn_pos + 5);82if (cn_pos != std::string::npos) {83cn_pos += 5;84if (pr[cn_pos] == 0x13 || pr[cn_pos] == 0x0c) {85cn_pos++; // Consume the type86int str_len = pr[cn_pos];87cn_pos++; // Consume the string length88merchant = QString::fromUtf8(pr.data() + cn_pos, str_len);89return true;90}91}92}93}94return false;95}97QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord* rec, BitcoinUnit unit)98{99int numBlocks;100interfaces::WalletTxStatus status;101bool inMempool;102std::vector<std::string> messages;103std::vector<std::string> payment_requests;104interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, messages, payment_requests, inMempool, numBlocks);106QString strHTML;108strHTML.reserve(4000);109strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";111int64_t nTime = wtx.time;112CAmount nCredit = wtx.credit;113CAmount nDebit = wtx.debit;114CAmount nNet = nCredit - nDebit;116strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(status, inMempool);117strHTML += "<br>";119strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";121//122// From123//124if (wtx.is_coinbase)125{126strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";127} else if (wtx.from) {128// Online transaction129strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(*wtx.from) + "<br>";130}131else132{133// Offline transaction134if (nNet > 0)135{136// Credit137CTxDestination address = DecodeDestination(rec->address);138if (IsValidDestination(address)) {139std::string name;140if (wallet.getAddress(address, &name, /*purpose=*/nullptr))141{142strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";143strHTML += "<b>" + tr("To") + ":</b> ";144strHTML += GUIUtil::HtmlEscape(rec->address);145QString addressOwned = tr("own address");146if (!name.empty())147strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(name) + ")";148else149strHTML += " (" + addressOwned + ")";150strHTML += "<br>";151}152}153}154}156//157// To158//159if (wtx.comment_to) {160// Online transaction161std::string strAddress = *wtx.comment_to;162strHTML += "<b>" + tr("To") + ":</b> ";163CTxDestination dest = DecodeDestination(strAddress);164std::string name;165if (wallet.getAddress(166dest, &name, /*purpose=*/nullptr) && !name.empty())167strHTML += GUIUtil::HtmlEscape(name) + " ";168strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";169}171//172// Amount173//174if (wtx.is_coinbase && nCredit == 0)175{176//177// Coinbase178//179CAmount nUnmatured = 0;180for (const CTxOut& txout : wtx.tx->vout)181nUnmatured += wallet.getCredit(txout);182strHTML += "<b>" + tr("Credit") + ":</b> ";183if (status.is_in_main_chain)184strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", status.blocks_to_maturity) + ")";185else186strHTML += "(" + tr("not accepted") + ")";187strHTML += "<br>";188}189else if (nNet > 0)190{191//192// Credit193//194strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";195}196else197{198bool all_from_me = std::all_of(wtx.txin_is_mine.begin(), wtx.txin_is_mine.end(), [](bool mine) { return mine; });199bool all_to_me = std::all_of(wtx.txout_is_mine.begin(), wtx.txout_is_mine.end(), [](bool mine) { return mine; });201if (all_from_me)202{203// Debit204//205auto mine = wtx.txout_is_mine.begin();206for (const CTxOut& txout : wtx.tx->vout)207{208// Ignore change209bool toSelf = *(mine++);210if (toSelf && all_from_me)211continue;213if (!wtx.comment_to) {214// Offline transaction215CTxDestination address;216if (ExtractDestination(txout.scriptPubKey, address))217{218strHTML += "<b>" + tr("To") + ":</b> ";219std::string name;220if (wallet.getAddress(221address, &name, /*purpose=*/nullptr) && !name.empty())222strHTML += GUIUtil::HtmlEscape(name) + " ";223strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));224if(toSelf)225strHTML += " (" + tr("own address") + ")";226strHTML += "<br>";227}228}230strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";231if(toSelf)232strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";233}235if (all_to_me)236{237// Payment to self238CAmount nChange = wtx.change;239CAmount nValue = nCredit - nChange;240strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";241strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";242}244CAmount nTxFee = nDebit - wtx.tx->GetValueOut();245if (nTxFee > 0)246strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";247}248else249{250//
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.