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.
1// Copyright (c) 2023-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/license/mit.5#ifndef BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H6#define BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H8#include <attributes.h>9#include <uint256.h>11#include <compare>12#include <cstddef>13#include <optional>14#include <string>15#include <string_view>16#include <tuple>17#include <type_traits>18#include <variant>20/** transaction_identifier represents the two canonical transaction identifier21* types (txid, wtxid).*/22template <bool has_witness>23class transaction_identifier24{25uint256 m_wrapped;27// Note: Use FromUint256 externally instead.28transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}30public:31transaction_identifier() : m_wrapped{} {}32consteval explicit transaction_identifier(std::string_view hex_str) : m_wrapped{uint256{hex_str}} {}34constexpr bool operator==(const transaction_identifier&) const = default;35constexpr auto operator<=>(const transaction_identifier&) const = default;37const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }38static transaction_identifier FromUint256(const uint256& id) { return {id}; }40/** Wrapped `uint256` methods. */41constexpr bool IsNull() const { return m_wrapped.IsNull(); }42constexpr void SetNull() { m_wrapped.SetNull(); }43static std::optional<transaction_identifier> FromHex(std::string_view hex)44{45auto u{uint256::FromHex(hex)};46if (!u) return std::nullopt;47return FromUint256(*u);48}49std::string GetHex() const { return m_wrapped.GetHex(); }50std::string ToString() const { return m_wrapped.ToString(); }51static constexpr auto size() { return decltype(m_wrapped)::size(); }52constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }53constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }54constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }55template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }56template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }57};59/** Txid commits to all transaction fields except the witness. */60using Txid = transaction_identifier<false>;61/** Wtxid commits to all transaction fields including the witness. */62using Wtxid = transaction_identifier<true>;64template <typename T>65concept TxidOrWtxid = std::is_same_v<T, Txid> || std::is_same_v<T, Wtxid>;67class GenTxid : public std::variant<Txid, Wtxid>68{69public:70using variant::variant;72bool IsWtxid() const { return std::holds_alternative<Wtxid>(*this); }74const uint256& ToUint256() const LIFETIMEBOUND75{76return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);77}79friend auto operator<=>(const GenTxid& a, const GenTxid& b)80{81// Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.82return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());83}84};86#endif // BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H