LCOV - code coverage report
Current view: top level - src/primitives - transaction.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 106 118 89.8 %
Date: 2026-10-19 02:26:17 Functions: 27 29 93.1 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2015-2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #include "primitives/transaction.h"
       8             : 
       9             : #include "hash.h"
      10             : #include "tinyformat.h"
      11             : #include "utilstrencodings.h"
      12             : 
      13        1200 : std::string BaseOutPoint::ToStringShort() const
      14             : {
      15        3600 :     return strprintf("%s-%u", hash.ToString().substr(0,64), n);
      16             : }
      17             : 
      18        2326 : std::string COutPoint::ToString() const
      19             : {
      20        6978 :     return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
      21             : }
      22             : 
      23           0 : std::string SaplingOutPoint::ToString() const
      24             : {
      25           0 :     return strprintf("SaplingOutPoint(%s, %u)", hash.ToString().substr(0, 10), n);
      26             : }
      27             : 
      28             : 
      29        9106 : CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
      30             : {
      31        9106 :     prevout = prevoutIn;
      32        9106 :     scriptSig = scriptSigIn;
      33        9106 :     nSequence = nSequenceIn;
      34        9106 : }
      35             : 
      36        8600 : CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
      37             : {
      38        8600 :     prevout = COutPoint(hashPrevTx, nOut);
      39        8600 :     scriptSig = scriptSigIn;
      40        8600 :     nSequence = nSequenceIn;
      41        8600 : }
      42             : 
      43    35312836 : bool CTxIn::IsZerocoinSpend() const
      44             : {
      45    70625572 :     return prevout.hash.IsNull() && scriptSig.IsZerocoinSpend();
      46             : }
      47             : 
      48    21151991 : bool CTxIn::IsZerocoinPublicSpend() const
      49             : {
      50    21151991 :     return scriptSig.IsZerocoinPublicSpend();
      51             : }
      52             : 
      53        2149 : std::string CTxIn::ToString() const
      54             : {
      55        2149 :     std::string str;
      56        2149 :     str += "CTxIn(";
      57        4298 :     str += prevout.ToString();
      58        2149 :     if (prevout.IsNull())
      59           1 :         if(IsZerocoinSpend())
      60           0 :             str += strprintf(", zerocoinspend %s...", HexStr(scriptSig).substr(0, 25));
      61             :         else
      62           4 :             str += strprintf(", coinbase %s", HexStr(scriptSig));
      63             :     else
      64       11181 :         str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
      65        2149 :     if (nSequence != std::numeric_limits<unsigned int>::max())
      66           0 :         str += strprintf(", nSequence=%u", nSequence);
      67        2149 :     str += ")";
      68        2149 :     return str;
      69             : }
      70             : 
      71       24342 : CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
      72             : {
      73       24342 :     nValue = nValueIn;
      74       24342 :     scriptPubKey = scriptPubKeyIn;
      75       24342 :     nRounds = -10;
      76       24342 : }
      77             : 
      78           0 : uint256 CTxOut::GetHash() const
      79             : {
      80           0 :     return SerializeHash(*this);
      81             : }
      82             : 
      83     8941484 : bool CTxOut::IsZerocoinMint() const
      84             : {
      85     8941484 :     return scriptPubKey.IsZerocoinMint();
      86             : }
      87             : 
      88        1816 : std::string CTxOut::ToString() const
      89             : {
      90        7262 :     return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0,30));
      91             : }
      92             : 
      93      818199 : CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(CTransaction::TxType::NORMAL), nLockTime(0) {}
      94      156978 : CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload) {}
      95             : 
      96      257021 : uint256 CMutableTransaction::GetHash() const
      97             : {
      98      257021 :     return SerializeHash(*this);
      99             : }
     100             : 
     101     2286399 : uint256 CTransaction::ComputeHash() const
     102             : {
     103     2286399 :     return SerializeHash(*this);
     104             : }
     105             : 
     106      277627 : size_t CTransaction::DynamicMemoryUsage() const
     107             : {
     108      277627 :     return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout);
     109             : }
     110             : 
     111             : /* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
     112       13616 : CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nType(TxType::NORMAL), nLockTime(0), hash() {}
     113     2006960 : CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload), hash(ComputeHash()) {}
     114     2576908 : CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload), hash(ComputeHash()) {}
     115             : 
     116    11997246 : bool CTransaction::HasZerocoinSpendInputs() const
     117             : {
     118    30559948 :     for (const CTxIn& txin: vin) {
     119    18562702 :         if (txin.IsZerocoinSpend() || txin.IsZerocoinPublicSpend())
     120           0 :             return true;
     121             :     }
     122    11997246 :     return false;
     123             : }
     124             : 
     125      312105 : bool CTransaction::HasZerocoinMintOutputs() const
     126             : {
     127     1150528 :     for(const CTxOut& txout : vout) {
     128      838422 :         if (txout.IsZerocoinMint())
     129           0 :             return true;
     130             :     }
     131      312105 :     return false;
     132             : }
     133             : 
     134    12099298 : bool CTransaction::IsCoinStake() const
     135             : {
     136    12099298 :     if (vin.empty())
     137             :         return false;
     138             : 
     139    12050852 :     bool fAllowNull = vin[0].IsZerocoinSpend();
     140    12120033 :     if (vin[0].prevout.IsNull() && !fAllowNull)
     141             :         return false;
     142             : 
     143    11981671 :     return (vout.size() >= 2 && vout[0].IsEmpty());
     144             : }
     145             : 
     146      787432 : bool CTransaction::HasExchangeAddr() const
     147             : {
     148     2847570 :     return std::any_of(vout.begin(), vout.end(), [](const auto& txout) { return txout.scriptPubKey.IsPayToExchangeAddress(); });
     149             : }
     150             : 
     151       11692 : bool CTransaction::HasP2CSOutputs() const
     152             : {
     153       25358 :     for(const CTxOut& txout : vout) {
     154       14547 :         if (txout.scriptPubKey.IsPayToColdStaking())
     155         881 :             return true;
     156             :     }
     157       10811 :     return false;
     158             : }
     159             : 
     160     7151274 : CAmount CTransaction::GetValueOut() const
     161             : {
     162     7151274 :     CAmount nValueOut = 0;
     163    21857486 :     for (const CTxOut& out : vout) {
     164             :         // PIVX: previously MoneyRange() was called here. This has been replaced with negative check and boundary wrap check.
     165    14706142 :         if (out.nValue < 0)
     166           0 :             throw std::runtime_error("CTransaction::GetValueOut() : value out of range : less than 0");
     167             : 
     168    14706142 :         if (nValueOut + out.nValue < nValueOut)
     169             :             throw std::runtime_error("CTransaction::GetValueOut() : value out of range : wraps the int64_t boundary");
     170             : 
     171    14706142 :         nValueOut += out.nValue;
     172             :     }
     173             : 
     174             :     // Sapling
     175     7151274 :     if (hasSaplingData() && sapData->valueBalance < 0) {
     176             :         // NB: negative valueBalance "takes" money from the transparent value pool just as outputs do
     177     1019081 :         nValueOut += -sapData->valueBalance;
     178             : 
     179             :         // Verify Sapling version
     180     1019081 :         if (!isSaplingVersion())
     181           0 :             throw std::runtime_error("GetValueOut(): invalid tx version");
     182             :     }
     183             : 
     184     7151274 :     return nValueOut;
     185             : }
     186             : 
     187     3809413 : CAmount CTransaction::GetShieldedValueIn() const
     188             : {
     189     3809413 :     CAmount nValue = 0;
     190             : 
     191     3809413 :     if (hasSaplingData() && sapData->valueBalance > 0) {
     192             :         // NB: positive valueBalance "gives" money to the transparent value pool just as inputs do
     193         740 :         nValue += sapData->valueBalance;
     194             : 
     195             :         // Verify Sapling
     196         740 :         if (!isSaplingVersion())
     197           0 :             throw std::runtime_error("GetValueOut(): invalid tx version");
     198             :     }
     199             : 
     200     3809413 :     return nValue;
     201             : }
     202             : 
     203      957333 : unsigned int CTransaction::GetTotalSize() const
     204             : {
     205      957333 :     return ::GetSerializeSize(*this, PROTOCOL_VERSION);
     206             : }
     207             : 
     208        1445 : std::string CTransaction::ToString() const
     209             : {
     210        1445 :     std::ostringstream ss;
     211        2890 :     ss << "CTransaction(hash=" << GetHash().ToString().substr(0, 10)
     212        2890 :        << ", ver=" << nVersion
     213        1445 :        << ", type=" << nType
     214        1445 :        << ", vin.size=" << vin.size()
     215        1445 :        << ", vout.size=" << vout.size()
     216        1445 :        << ", nLockTime=" << nLockTime;
     217        1445 :     if (IsShieldedTx()) {
     218        1066 :         ss << ", valueBalance=" << sapData->valueBalance
     219        1066 :            << ", vShieldedSpend.size=" << sapData->vShieldedSpend.size()
     220        1066 :            << ", vShieldedOutput.size=" << sapData->vShieldedOutput.size();
     221             :     }
     222        1445 :     if (IsSpecialTx()) {
     223           0 :         ss << ", extraPayload.size=" << extraPayload->size();
     224             :     }
     225        1445 :     ss << ")\n";
     226        3025 :     for (const auto& in : vin)
     227        4740 :         ss << "    " << in.ToString() << "\n";
     228        3261 :     for (const auto& out : vout)
     229        5448 :         ss << "    " << out.ToString() << "\n";
     230        1445 :     return ss.str();
     231             : }

Generated by: LCOV version 1.14