transaction.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-2022 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 <hash.h> 10 #include <script/script.h> 11 #include <serialize.h> 12 #include <tinyformat.h> 13 #include <uint256.h> 14 #include <util/strencodings.h> 15 #include <util/transaction_identifier.h> 16 17 #include <algorithm> 18 #include <cassert> 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() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} 67 CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), 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), nVersion(tx.nVersion), 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)), nVersion(tx.nVersion), 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::GetTotalSize() 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=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n", 119 GetHash().ToString().substr(0,10), 120 nVersion, 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 }