Coverage Report

Created: 2026-04-29 19:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/primitives/transaction_identifier.h
Line
Count
Source
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
3.30M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<false>::transaction_identifier(uint256 const&)
Line
Count
Source
29
2.11M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<true>::transaction_identifier(uint256 const&)
Line
Count
Source
29
1.18M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
30
31
772M
    constexpr int Compare(const transaction_identifier<has_witness>& other) const { return m_wrapped.Compare(other.m_wrapped); }
transaction_identifier<false>::Compare(transaction_identifier<false> const&) const
Line
Count
Source
31
742M
    constexpr int Compare(const transaction_identifier<has_witness>& other) const { return m_wrapped.Compare(other.m_wrapped); }
transaction_identifier<true>::Compare(transaction_identifier<true> const&) const
Line
Count
Source
31
29.9M
    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
1.72M
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<true>::transaction_identifier()
Line
Count
Source
40
34.8k
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<false>::transaction_identifier()
Line
Count
Source
40
1.69M
    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
181M
    bool operator==(const Other& other) const { return Compare(other) == 0; }
bool transaction_identifier<false>::operator==<transaction_identifier<false>>(transaction_identifier<false> const&) const
Line
Count
Source
44
151M
    bool operator==(const Other& other) const { return Compare(other) == 0; }
bool transaction_identifier<true>::operator==<transaction_identifier<true>>(transaction_identifier<true> const&) const
Line
Count
Source
44
29.8M
    bool operator==(const Other& other) const { return Compare(other) == 0; }
45
    template <typename Other>
46
591M
    std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; }
std::strong_ordering transaction_identifier<false>::operator<=><transaction_identifier<false>>(transaction_identifier<false> const&) const
Line
Count
Source
46
591M
    std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; }
std::strong_ordering transaction_identifier<true>::operator<=><transaction_identifier<true>>(transaction_identifier<true> const&) const
Line
Count
Source
46
100k
    std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; }
47
48
380M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<false>::ToUint256() const
Line
Count
Source
48
351M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<true>::ToUint256() const
Line
Count
Source
48
28.8M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
49
3.30M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<false>::FromUint256(uint256 const&)
Line
Count
Source
49
2.11M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<true>::FromUint256(uint256 const&)
Line
Count
Source
49
1.18M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
50
51
    /** Wrapped `uint256` methods. */
52
26.7M
    constexpr bool IsNull() const { return m_wrapped.IsNull(); }
53
46.0k
    constexpr void SetNull() { m_wrapped.SetNull(); }
54
    static std::optional<transaction_identifier> FromHex(std::string_view hex)
55
670
    {
56
670
        auto u{uint256::FromHex(hex)};
57
670
        if (!u) return std::nullopt;
58
393
        return FromUint256(*u);
59
670
    }
transaction_identifier<false>::FromHex(std::basic_string_view<char, std::char_traits<char>>)
Line
Count
Source
55
586
    {
56
586
        auto u{uint256::FromHex(hex)};
57
586
        if (!u) return std::nullopt;
58
391
        return FromUint256(*u);
59
586
    }
transaction_identifier<true>::FromHex(std::basic_string_view<char, std::char_traits<char>>)
Line
Count
Source
55
84
    {
56
84
        auto u{uint256::FromHex(hex)};
57
84
        if (!u) return std::nullopt;
58
2
        return FromUint256(*u);
59
84
    }
60
252k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<true>::GetHex[abi:cxx11]() const
Line
Count
Source
60
14.0k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<false>::GetHex[abi:cxx11]() const
Line
Count
Source
60
238k
    std::string GetHex() const { return m_wrapped.GetHex(); }
61
849k
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<false>::ToString[abi:cxx11]() const
Line
Count
Source
61
729k
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<true>::ToString[abi:cxx11]() const
Line
Count
Source
61
119k
    std::string ToString() const { return m_wrapped.ToString(); }
62
6
    static constexpr auto size() { return decltype(m_wrapped)::size(); }
transaction_identifier<false>::size()
Line
Count
Source
62
6
    static constexpr auto size() { return decltype(m_wrapped)::size(); }
Unexecuted instantiation: transaction_identifier<true>::size()
63
6
    constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }
64
266k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<false>::begin() const
Line
Count
Source
64
541
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<true>::begin() const
Line
Count
Source
64
266k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
65
1.08k
    constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
Unexecuted instantiation: transaction_identifier<false>::end() const
transaction_identifier<true>::end() const
Line
Count
Source
65
1.08k
    constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
66
33.2M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<SizeComputer&, TransactionSerParams>>(ParamsStream<SizeComputer&, TransactionSerParams>&) const
Line
Count
Source
66
2.60M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<DataStream&, TransactionSerParams>>(ParamsStream<DataStream&, TransactionSerParams>&) const
Line
Count
Source
66
50.7k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<HashWriter&, TransactionSerParams>>(ParamsStream<HashWriter&, TransactionSerParams>&) const
Line
Count
Source
66
1.84M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<true>::Serialize<HashWriter>(HashWriter&) const
Line
Count
Source
66
888
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<HashWriter>(HashWriter&) const
Line
Count
Source
66
21.4M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<DataStream>(DataStream&) const
Line
Count
Source
66
7.04M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<VectorWriter&, TransactionSerParams>>(ParamsStream<VectorWriter&, TransactionSerParams>&) const
Line
Count
Source
66
69.0k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<BufferedWriter<AutoFile>&, TransactionSerParams>>(ParamsStream<BufferedWriter<AutoFile>&, TransactionSerParams>&) const
Line
Count
Source
66
185k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<ParamsStream<AutoFile&, TransactionSerParams>>(ParamsStream<AutoFile&, TransactionSerParams>&) const
Line
Count
Source
66
2.36k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<AutoFile>(AutoFile&) const
Line
Count
Source
66
7.32k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
67
679k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<ParamsStream<DataStream&, TransactionSerParams>>(ParamsStream<DataStream&, TransactionSerParams>&)
Line
Count
Source
67
125k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<DataStream>(DataStream&)
Line
Count
Source
67
12.5k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<SpanReader>(SpanReader&)
Line
Count
Source
67
221k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<ParamsStream<SpanReader&, TransactionSerParams>>(ParamsStream<SpanReader&, TransactionSerParams>&)
Line
Count
Source
67
310k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<AutoFile>(AutoFile&)
Line
Count
Source
67
6.56k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<ParamsStream<AutoFile&, TransactionSerParams>>(ParamsStream<AutoFile&, TransactionSerParams>&)
Line
Count
Source
67
467
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<ParamsStream<BufferedFile&, TransactionSerParams>>(ParamsStream<BufferedFile&, TransactionSerParams>&)
Line
Count
Source
67
1.84k
    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
1.45M
    bool IsWtxid() const { return std::holds_alternative<Wtxid>(*this); }
84
85
    const uint256& ToUint256() const LIFETIMEBOUND
86
11.3M
    {
87
11.3M
        return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);
uint256 const& GenTxid::ToUint256() const::'lambda'(auto const&)::operator()<transaction_identifier<false>>(auto const&) const
Line
Count
Source
87
4.69M
        return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);
uint256 const& GenTxid::ToUint256() const::'lambda'(auto const&)::operator()<transaction_identifier<true>>(auto const&) const
Line
Count
Source
87
6.63M
        return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);
88
11.3M
    }
89
90
    friend auto operator<=>(const GenTxid& a, const GenTxid& b)
91
694k
    {
92
        // Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.
93
694k
        return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());
94
694k
    }
95
};
96
97
#endif // BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H