transaction_identifier.h raw

   1  // Copyright (c) 2023-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or https://opensource.org/license/mit.
   4  
   5  #ifndef BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H
   6  #define BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H
   7  
   8  #include <attributes.h>
   9  #include <uint256.h>
  10  #include <util/types.h>
  11  
  12  #include <compare>
  13  #include <cstddef>
  14  #include <optional>
  15  #include <string>
  16  #include <string_view>
  17  #include <tuple>
  18  #include <type_traits>
  19  #include <variant>
  20  
  21  /** transaction_identifier represents the two canonical transaction identifier
  22   * types (txid, wtxid).*/
  23  template <bool has_witness>
  24  class transaction_identifier
  25  {
  26      uint256 m_wrapped;
  27  
  28      // Note: Use FromUint256 externally instead.
  29      transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
  30  
  31      constexpr int Compare(const transaction_identifier<has_witness>& other) const { return m_wrapped.Compare(other.m_wrapped); }
  32      template <typename Other>
  33      constexpr int Compare(const Other& other) const
  34      {
  35          static_assert(ALWAYS_FALSE<Other>, "Forbidden comparison type");
  36          return 0;
  37      }
  38  
  39  public:
  40      transaction_identifier() : m_wrapped{} {}
  41      consteval explicit transaction_identifier(std::string_view hex_str) : m_wrapped{uint256{hex_str}} {}
  42  
  43      template <typename Other>
  44      bool operator==(const Other& other) const { return Compare(other) == 0; }
  45      template <typename Other>
  46      std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; }
  47  
  48      const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
  49      static transaction_identifier FromUint256(const uint256& id) { return {id}; }
  50  
  51      /** Wrapped `uint256` methods. */
  52      constexpr bool IsNull() const { return m_wrapped.IsNull(); }
  53      constexpr void SetNull() { m_wrapped.SetNull(); }
  54      static std::optional<transaction_identifier> FromHex(std::string_view hex)
  55      {
  56          auto u{uint256::FromHex(hex)};
  57          if (!u) return std::nullopt;
  58          return FromUint256(*u);
  59      }
  60      std::string GetHex() const { return m_wrapped.GetHex(); }
  61      std::string ToString() const { return m_wrapped.ToString(); }
  62      static constexpr auto size() { return decltype(m_wrapped)::size(); }
  63      constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }
  64      constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
  65      constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
  66      template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
  67      template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
  68  };
  69  
  70  /** Txid commits to all transaction fields except the witness. */
  71  using Txid = transaction_identifier<false>;
  72  /** Wtxid commits to all transaction fields including the witness. */
  73  using Wtxid = transaction_identifier<true>;
  74  
  75  template <typename T>
  76  concept TxidOrWtxid = std::is_same_v<T, Txid> || std::is_same_v<T, Wtxid>;
  77  
  78  class GenTxid : public std::variant<Txid, Wtxid>
  79  {
  80  public:
  81      using variant::variant;
  82  
  83      bool IsWtxid() const { return std::holds_alternative<Wtxid>(*this); }
  84  
  85      const uint256& ToUint256() const LIFETIMEBOUND
  86      {
  87          return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);
  88      }
  89  
  90      friend auto operator<=>(const GenTxid& a, const GenTxid& b)
  91      {
  92          // Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.
  93          return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());
  94      }
  95  };
  96  
  97  #endif // BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H
  98