transaction.cpp raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #include <primitives/transaction.h>
   7  
   8  #include <consensus/amount.h>
   9  #include <crypto/hex_base.h>
  10  #include <hash.h>
  11  #include <primitives/transaction_identifier.h>
  12  #include <script/script.h>
  13  #include <serialize.h>
  14  #include <tinyformat.h>
  15  
  16  #include <algorithm>
  17  #include <cassert>
  18  #include <span>
  19  #include <stdexcept>
  20  
  21  std::string COutPoint::ToString() const
  22  {
  23      return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
  24  }
  25  
  26  CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
  27  {
  28      prevout = prevoutIn;
  29      scriptSig = scriptSigIn;
  30      nSequence = nSequenceIn;
  31  }
  32  
  33  CTxIn::CTxIn(Txid hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
  34  {
  35      prevout = COutPoint(hashPrevTx, nOut);
  36      scriptSig = scriptSigIn;
  37      nSequence = nSequenceIn;
  38  }
  39  
  40  std::string CTxIn::ToString() const
  41  {
  42      std::string str;
  43      str += "CTxIn(";
  44      str += prevout.ToString();
  45      if (prevout.IsNull())
  46          str += strprintf(", coinbase %s", HexStr(scriptSig));
  47      else
  48          str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
  49      if (nSequence != SEQUENCE_FINAL)
  50          str += strprintf(", nSequence=%u", nSequence);
  51      str += ")";
  52      return str;
  53  }
  54  
  55  CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
  56  {
  57      nValue = nValueIn;
  58      scriptPubKey = scriptPubKeyIn;
  59  }
  60  
  61  std::string CTxOut::ToString() const
  62  {
  63      return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0, 30));
  64  }
  65  
  66  CMutableTransaction::CMutableTransaction() : version{CTransaction::CURRENT_VERSION}, nLockTime{0} {}
  67  CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), vout(tx.vout), version{tx.version}, nLockTime{tx.nLockTime} {}
  68  
  69  Txid CMutableTransaction::GetHash() const
  70  {
  71      return Txid::FromUint256((HashWriter{} << TX_NO_WITNESS(*this)).GetHash());
  72  }
  73  
  74  bool CTransaction::ComputeHasWitness() const
  75  {
  76      return std::any_of(vin.begin(), vin.end(), [](const auto& input) {
  77          return !input.scriptWitness.IsNull();
  78      });
  79  }
  80  
  81  Txid CTransaction::ComputeHash() const
  82  {
  83      return Txid::FromUint256((HashWriter{} << TX_NO_WITNESS(*this)).GetHash());
  84  }
  85  
  86  Wtxid CTransaction::ComputeWitnessHash() const
  87  {
  88      if (!HasWitness()) {
  89          return Wtxid::FromUint256(hash.ToUint256());
  90      }
  91  
  92      return Wtxid::FromUint256((HashWriter{} << TX_WITH_WITNESS(*this)).GetHash());
  93  }
  94  
  95  CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), version{tx.version}, nLockTime{tx.nLockTime}, m_has_witness{ComputeHasWitness()}, hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
  96  CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), version{tx.version}, nLockTime{tx.nLockTime}, m_has_witness{ComputeHasWitness()}, hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
  97  
  98  CAmount CTransaction::GetValueOut() const
  99  {
 100      CAmount nValueOut = 0;
 101      for (const auto& tx_out : vout) {
 102          if (!MoneyRange(tx_out.nValue) || !MoneyRange(nValueOut + tx_out.nValue))
 103              throw std::runtime_error(std::string(__func__) + ": value out of range");
 104          nValueOut += tx_out.nValue;
 105      }
 106      assert(MoneyRange(nValueOut));
 107      return nValueOut;
 108  }
 109  
 110  unsigned int CTransaction::ComputeTotalSize() const
 111  {
 112      return ::GetSerializeSize(TX_WITH_WITNESS(*this));
 113  }
 114  
 115  std::string CTransaction::ToString() const
 116  {
 117      std::string str;
 118      str += strprintf("CTransaction(hash=%s, ver=%u, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
 119          GetHash().ToString().substr(0,10),
 120          version,
 121          vin.size(),
 122          vout.size(),
 123          nLockTime);
 124      for (const auto& tx_in : vin)
 125          str += "    " + tx_in.ToString() + "\n";
 126      for (const auto& tx_in : vin)
 127          str += "    " + tx_in.scriptWitness.ToString() + "\n";
 128      for (const auto& tx_out : vout)
 129          str += "    " + tx_out.ToString() + "\n";
 130      return str;
 131  }
 132