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