Inside Bitcoin
Opening the selected file…
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.
251if (tx.HasWitness()) {252flags |= 1;253}254}255if (flags) {256/* Use extended format in case witnesses are to be serialized. */257std::vector<CTxIn> vinDummy;258s << vinDummy;259s << flags;260}261s << tx.vin;262s << tx.vout;263if (flags & 1) {264for (size_t i = 0; i < tx.vin.size(); i++) {265s << tx.vin[i].scriptWitness.stack;266}267}268s << tx.nLockTime;269}271template<typename TxType>272inline CAmount CalculateOutputValue(const TxType& tx)273{274return std::accumulate(tx.vout.cbegin(), tx.vout.cend(), CAmount{0}, [](CAmount sum, const auto& txout) { return sum + txout.nValue; });275}277struct EqualsOptions {278bool include_script_sig{true};279bool include_witness_data{true};280};283/** The basic transaction that is broadcasted on the network and contained in284* blocks. A transaction can contain multiple inputs and outputs.285*/286class CTransaction287{288public:289// Default transaction version.290static constexpr uint32_t CURRENT_VERSION{2};292// The local variables are made const to prevent unintended modification293// without updating the cached hash value. However, CTransaction is not294// actually immutable; deserialization and assignment are implemented,295// and bypass the constness. This is safe, as they update the entire296// structure, including the hash.297const std::vector<CTxIn> vin;298const std::vector<CTxOut> vout;299const uint32_t version;300const uint32_t nLockTime;302private:303/** Memory only. */304const bool m_has_witness;305const Txid hash;306const Wtxid m_witness_hash;308Txid ComputeHash() const;309Wtxid ComputeWitnessHash() const;311bool ComputeHasWitness() const;313public:314/** Convert a CMutableTransaction into a CTransaction. */315explicit CTransaction(const CMutableTransaction& tx);316explicit CTransaction(CMutableTransaction&& tx);318template <typename Stream>319inline void Serialize(Stream& s) const {320SerializeTransaction(*this, s, s.template GetParams<TransactionSerParams>());321}323/** This deserializing constructor is provided instead of an Unserialize method.324* Unserialize is not possible, since it would require overwriting const fields. */325template <typename Stream>326CTransaction(deserialize_type, const TransactionSerParams& params, Stream& s) : CTransaction(CMutableTransaction(deserialize, params, s)) {}327template <typename Stream>328CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}330bool IsNull() const {331return vin.empty() && vout.empty();332}334const Txid& GetHash() const LIFETIMEBOUND { return hash; }335const Wtxid& GetWitnessHash() const LIFETIMEBOUND { return m_witness_hash; };337// Return sum of txouts.338CAmount GetValueOut() const;340/**341* Calculate the total transaction size in bytes, including witness data.342* "Total Size" defined in BIP141 and BIP144.343* @return Total transaction size in bytes344*/345unsigned int ComputeTotalSize() const;347bool IsCoinBase() const348{349return (vin.size() == 1 && vin[0].prevout.IsNull());350}352bool Equals(const CTransaction& other, const EqualsOptions opts = {}) const353{354return nLockTime == other.nLockTime &&355version == other.version &&356vout == other.vout &&357std::ranges::equal(vin, other.vin, [&opts](const CTxIn& self, const CTxIn& other) {358return self.prevout == other.prevout &&359self.nSequence == other.nSequence &&360(opts.include_script_sig ? self.scriptSig == other.scriptSig : true) &&361(opts.include_witness_data ? self.scriptWitness.stack == other.scriptWitness.stack : true);362});363}365std::string ToString() const;367bool HasWitness() const { return m_has_witness; }368};370/** A mutable version of CTransaction. */371struct CMutableTransaction372{373std::vector<CTxIn> vin;374std::vector<CTxOut> vout;375uint32_t version;376uint32_t nLockTime;378explicit CMutableTransaction();379explicit CMutableTransaction(const CTransaction& tx);381template <typename Stream>382inline void Serialize(Stream& s) const {383SerializeTransaction(*this, s, s.template GetParams<TransactionSerParams>());384}386template <typename Stream>387inline void Unserialize(Stream& s) {388UnserializeTransaction(*this, s, s.template GetParams<TransactionSerParams>());389}391template <typename Stream>392CMutableTransaction(deserialize_type, const TransactionSerParams& params, Stream& s) {393UnserializeTransaction(*this, s, params);394}396template <typename Stream>397CMutableTransaction(deserialize_type, Stream& s) {398Unserialize(s);399}401/** Compute the hash of this CMutableTransaction. This is computed on the402* fly, as opposed to GetHash() in CTransaction, which uses a cached result.403*/404Txid GetHash() const;406bool HasWitness() const407{408for (size_t i = 0; i < vin.size(); i++) {409if (!vin[i].scriptWitness.IsNull()) {410return true;411}412}413return false;414}415};417typedef std::shared_ptr<const CTransaction> CTransactionRef;418template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }420namespace std {421/** Disable default std::hash for CTransactionRef to prevent accidentally422* comparing by pointer. Use CTransactionRefHash or provide a custom423* hasher. */424template <>425struct hash<CTransactionRef> {426hash() = delete;427// Belt-and-suspenders, already implied by the above.428size_t operator()(const CTransactionRef&) const = delete;429};430} // namespace std432#endif // BITCOIN_PRIMITIVES_TRANSACTION_H