Coverage Report

Created: 2026-09-14 20:36

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
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>
19
20
/** transaction_identifier represents the two canonical transaction identifier
21
 * types (txid, wtxid).*/
22
template <bool has_witness>
23
class transaction_identifier
24
{
25
    uint256 m_wrapped;
26
27
    // Note: Use FromUint256 externally instead.
28
3.96M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<false>::transaction_identifier(uint256 const&)
Line
Count
Source
28
2.53M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<true>::transaction_identifier(uint256 const&)
Line
Count
Source
28
1.43M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
29
30
public:
31
10.0M
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<true>::transaction_identifier()
Line
Count
Source
31
206k
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<false>::transaction_identifier()
Line
Count
Source
31
9.80M
    transaction_identifier() : m_wrapped{} {}
32
    consteval explicit transaction_identifier(std::string_view hex_str) : m_wrapped{uint256{hex_str}} {}
33
34
134M
    constexpr bool operator==(const transaction_identifier&) const = default;
transaction_identifier<false>::operator==(transaction_identifier<false> const&) const
Line
Count
Source
34
133M
    constexpr bool operator==(const transaction_identifier&) const = default;
transaction_identifier<true>::operator==(transaction_identifier<true> const&) const
Line
Count
Source
34
322k
    constexpr bool operator==(const transaction_identifier&) const = default;
35
901M
    constexpr auto operator<=>(const transaction_identifier&) const = default;
transaction_identifier<false>::operator<=>(transaction_identifier<false> const&) const
Line
Count
Source
35
893M
    constexpr auto operator<=>(const transaction_identifier&) const = default;
transaction_identifier<true>::operator<=>(transaction_identifier<true> const&) const
Line
Count
Source
35
7.32M
    constexpr auto operator<=>(const transaction_identifier&) const = default;
36
37
317M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<false>::ToUint256() const
Line
Count
Source
37
309M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<true>::ToUint256() const
Line
Count
Source
37
7.88M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
38
3.96M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<false>::FromUint256(uint256 const&)
Line
Count
Source
38
2.53M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<true>::FromUint256(uint256 const&)
Line
Count
Source
38
1.43M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
39
40
    /** Wrapped `uint256` methods. */
41
22.0M
    constexpr bool IsNull() const { return m_wrapped.IsNull(); }
42
45.2k
    constexpr void SetNull() { m_wrapped.SetNull(); }
43
    static std::optional<transaction_identifier> FromHex(std::string_view hex)
44
1.16k
    {
45
1.16k
        auto u{uint256::FromHex(hex)};
46
1.16k
        if (!u) return std::nullopt;
47
875
        return FromUint256(*u);
48
1.16k
    }
transaction_identifier<false>::FromHex(std::basic_string_view<char, std::char_traits<char>>)
Line
Count
Source
44
1.08k
    {
45
1.08k
        auto u{uint256::FromHex(hex)};
46
1.08k
        if (!u) return std::nullopt;
47
873
        return FromUint256(*u);
48
1.08k
    }
transaction_identifier<true>::FromHex(std::basic_string_view<char, std::char_traits<char>>)
Line
Count
Source
44
84
    {
45
84
        auto u{uint256::FromHex(hex)};
46
84
        if (!u) return std::nullopt;
47
2
        return FromUint256(*u);
48
84
    }
49
279k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<true>::GetHex[abi:cxx11]() const
Line
Count
Source
49
14.8k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<false>::GetHex[abi:cxx11]() const
Line
Count
Source
49
264k
    std::string GetHex() const { return m_wrapped.GetHex(); }
50
897k
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<false>::ToString[abi:cxx11]() const
Line
Count
Source
50
733k
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<true>::ToString[abi:cxx11]() const
Line
Count
Source
50
163k
    std::string ToString() const { return m_wrapped.ToString(); }
51
6
    static constexpr auto size() { return decltype(m_wrapped)::size(); }
transaction_identifier<false>::size()
Line
Count
Source
51
6
    static constexpr auto size() { return decltype(m_wrapped)::size(); }
Unexecuted instantiation: transaction_identifier<true>::size()
52
6
    constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }
transaction_identifier<false>::data() const
Line
Count
Source
52
6
    constexpr const std::byte* data() const { return reinterpret_cast<const std::byte*>(m_wrapped.data()); }
Unexecuted instantiation: transaction_identifier<true>::data() const
53
335k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<false>::begin() const
Line
Count
Source
53
933
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<true>::begin() const
Line
Count
Source
53
334k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
54
970
    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
54
970
    constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
55
35.9M
    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
55
4.47M
    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
55
124k
    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
55
2.09M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<true>::Serialize<HashWriter>(HashWriter&) const
Line
Count
Source
55
888
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<HashWriter>(HashWriter&) const
Line
Count
Source
55
21.4M
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<SizeComputer>(SizeComputer&) const
Line
Count
Source
55
1.48k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<DataStream>(DataStream&) const
Line
Count
Source
55
7.48M
    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
55
76.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
55
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
55
2.51k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<false>::Serialize<AutoFile>(AutoFile&) const
Line
Count
Source
55
7.33k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<true>::Serialize<DataStream>(DataStream&) const
Line
Count
Source
55
17.9k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
Unexecuted instantiation: void transaction_identifier<true>::Serialize<ParamsStream<DataStream&, TransactionSerParams>>(ParamsStream<DataStream&, TransactionSerParams>&) const
56
781k
    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
56
138k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<DataStream>(DataStream&)
Line
Count
Source
56
14.5k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<SpanReader>(SpanReader&)
Line
Count
Source
56
280k
    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
56
339k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<AutoFile>(AutoFile&)
Line
Count
Source
56
6.57k
    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
56
517
    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
56
2.14k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<true>::Unserialize<ParamsStream<SpanReader&, TransactionSerParams>>(ParamsStream<SpanReader&, TransactionSerParams>&)
Line
Count
Source
56
4
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
57
};
58
59
/** Txid commits to all transaction fields except the witness. */
60
using Txid = transaction_identifier<false>;
61
/** Wtxid commits to all transaction fields including the witness. */
62
using Wtxid = transaction_identifier<true>;
63
64
template <typename T>
65
concept TxidOrWtxid = std::is_same_v<T, Txid> || std::is_same_v<T, Wtxid>;
66
67
class GenTxid : public std::variant<Txid, Wtxid>
68
{
69
public:
70
    using variant::variant;
71
72
1.50M
    bool IsWtxid() const { return std::holds_alternative<Wtxid>(*this); }
73
74
    const uint256& ToUint256() const LIFETIMEBOUND
75
11.4M
    {
76
11.4M
        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
76
4.61M
        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
76
6.86M
        return std::visit([](const auto& id) -> const uint256& { return id.ToUint256(); }, *this);
77
11.4M
    }
78
79
    friend auto operator<=>(const GenTxid& a, const GenTxid& b)
80
719k
    {
81
        // Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.
82
719k
        return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());
83
719k
    }
84
};
85
86
#endif // BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H