transaction_identifier.h raw

   1  #ifndef LIMENKA_UTIL_TRANSACTION_IDENTIFIER_H
   2  #define LIMENKA_UTIL_TRANSACTION_IDENTIFIER_H
   3  
   4  #include <attributes.h>
   5  #include <uint256.h>
   6  #include <util/types.h>
   7  
   8  /** transaction_identifier represents the two canonical transaction identifier
   9   * types (txid, wtxid).*/
  10  template <bool has_witness>
  11  class transaction_identifier
  12  {
  13      uint256 m_wrapped;
  14  
  15      // Note: Use FromUint256 externally instead.
  16      transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
  17  
  18      // TODO: Comparisons with uint256 should be disallowed once we have
  19      // converted most of the code to using the new txid types.
  20      constexpr int Compare(const uint256& other) const { return m_wrapped.Compare(other); }
  21      constexpr int Compare(const transaction_identifier<has_witness>& other) const { return m_wrapped.Compare(other.m_wrapped); }
  22      template <typename Other>
  23      constexpr int Compare(const Other& other) const
  24      {
  25          static_assert(ALWAYS_FALSE<Other>, "Forbidden comparison type");
  26          return 0;
  27      }
  28  
  29  public:
  30      transaction_identifier() : m_wrapped{} {}
  31  
  32      template <typename Other>
  33      bool operator==(const Other& other) const { return Compare(other) == 0; }
  34      template <typename Other>
  35      bool operator!=(const Other& other) const { return Compare(other) != 0; }
  36      template <typename Other>
  37      bool operator<(const Other& other) const { return Compare(other) < 0; }
  38  
  39      const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
  40      static transaction_identifier FromUint256(const uint256& id) { return {id}; }
  41  
  42      /** Wrapped `uint256` methods. */
  43      constexpr bool IsNull() const { return m_wrapped.IsNull(); }
  44      constexpr void SetNull() { m_wrapped.SetNull(); }
  45      static std::optional<transaction_identifier> FromHex(std::string_view hex)
  46      {
  47          auto u{uint256::FromHex(hex)};
  48          if (!u) return std::nullopt;
  49          return FromUint256(*u);
  50      }
  51      std::string GetHex() const { return m_wrapped.GetHex(); }
  52      std::string ToString() const { return m_wrapped.ToString(); }
  53      static constexpr auto size() { return decltype(m_wrapped)::size(); }
  54      constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }
  55      constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
  56      constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
  57      template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
  58      template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
  59  
  60      /** Conversion function to `uint256`.
  61       *
  62       * Note: new code should use `ToUint256`.
  63       *
  64       * TODO: This should be removed once the majority of the code has switched
  65       * to using the Txid and Wtxid types. Until then it makes for a smoother
  66       * transition to allow this conversion. */
  67      operator const uint256&() const LIFETIMEBOUND { return m_wrapped; }
  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  #endif // LIMENKA_UTIL_TRANSACTION_IDENTIFIER_H
  76