Coverage Report

Created: 2026-08-14 20:23

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.46M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<false>::transaction_identifier(uint256 const&)
Line
Count
Source
28
2.19M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
transaction_identifier<true>::transaction_identifier(uint256 const&)
Line
Count
Source
28
1.26M
    transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
29
30
public:
31
9.66M
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<true>::transaction_identifier()
Line
Count
Source
31
201k
    transaction_identifier() : m_wrapped{} {}
transaction_identifier<false>::transaction_identifier()
Line
Count
Source
31
9.46M
    transaction_identifier() : m_wrapped{} {}
32
    consteval explicit transaction_identifier(std::string_view hex_str) : m_wrapped{uint256{hex_str}} {}
33
34
169M
    constexpr bool operator==(const transaction_identifier&) const = default;
transaction_identifier<false>::operator==(transaction_identifier<false> const&) const
Line
Count
Source
34
168M
    constexpr bool operator==(const transaction_identifier&) const = default;
transaction_identifier<true>::operator==(transaction_identifier<true> const&) const
Line
Count
Source
34
372k
    constexpr bool operator==(const transaction_identifier&) const = default;
35
1.19G
    constexpr auto operator<=>(const transaction_identifier&) const = default;
transaction_identifier<false>::operator<=>(transaction_identifier<false> const&) const
Line
Count
Source
35
1.18G
    constexpr auto operator<=>(const transaction_identifier&) const = default;
transaction_identifier<true>::operator<=>(transaction_identifier<true> const&) const
Line
Count
Source
35
7.52M
    constexpr auto operator<=>(const transaction_identifier&) const = default;
36
37
373M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<false>::ToUint256() const
Line
Count
Source
37
366M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
transaction_identifier<true>::ToUint256() const
Line
Count
Source
37
7.76M
    const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
38
3.46M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<false>::FromUint256(uint256 const&)
Line
Count
Source
38
2.19M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
transaction_identifier<true>::FromUint256(uint256 const&)
Line
Count
Source
38
1.26M
    static transaction_identifier FromUint256(const uint256& id) { return {id}; }
39
40
    /** Wrapped `uint256` methods. */
41
29.4M
    constexpr bool IsNull() const { return m_wrapped.IsNull(); }
42
49.6k
    constexpr void SetNull() { m_wrapped.SetNull(); }
43
    static std::optional<transaction_identifier> FromHex(std::string_view hex)
44
779
    {
45
779
        auto u{uint256::FromHex(hex)};
46
779
        if (!u) return std::nullopt;
47
497
        return FromUint256(*u);
48
779
    }
transaction_identifier<false>::FromHex(std::basic_string_view<char, std::char_traits<char>>)
Line
Count
Source
44
695
    {
45
695
        auto u{uint256::FromHex(hex)};
46
695
        if (!u) return std::nullopt;
47
495
        return FromUint256(*u);
48
695
    }
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
267k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<true>::GetHex[abi:cxx11]() const
Line
Count
Source
49
14.3k
    std::string GetHex() const { return m_wrapped.GetHex(); }
transaction_identifier<false>::GetHex[abi:cxx11]() const
Line
Count
Source
49
252k
    std::string GetHex() const { return m_wrapped.GetHex(); }
50
1.00M
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<false>::ToString[abi:cxx11]() const
Line
Count
Source
50
826k
    std::string ToString() const { return m_wrapped.ToString(); }
transaction_identifier<true>::ToString[abi:cxx11]() const
Line
Count
Source
50
181k
    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
289k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<false>::begin() const
Line
Count
Source
53
889
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
transaction_identifier<true>::begin() const
Line
Count
Source
53
288k
    constexpr const std::byte* begin() const { return reinterpret_cast<const std::byte*>(m_wrapped.begin()); }
54
974
    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
974
    constexpr const std::byte* end() const { return reinterpret_cast<const std::byte*>(m_wrapped.end()); }
55
33.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
2.90M
    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
130k
    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
1.93M
    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.45k
    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.20M
    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
72.4k
    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
192k
    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.46k
    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.31k
    template <typename Stream> void Serialize(Stream& s) const { m_wrapped.Serialize(s); }
void transaction_identifier<true>::Serialize<DataStream>(DataStream&) const
Line
Count
Source
55
23.5k
    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
762k
    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
13.6k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<SpanReader>(SpanReader&)
Line
Count
Source
56
271k
    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
329k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
void transaction_identifier<false>::Unserialize<AutoFile>(AutoFile&)
Line
Count
Source
56
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
56
477
    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.15k
    template <typename Stream> void Unserialize(Stream& s) { m_wrapped.Unserialize(s); }
Unexecuted instantiation: void transaction_identifier<true>::Unserialize<ParamsStream<SpanReader&, TransactionSerParams>>(ParamsStream<SpanReader&, TransactionSerParams>&)
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.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
76
6.72M
        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
717k
    {
81
        // Use a reference for read-only access to the hash, avoiding a copy that might not be optimized away.
82
717k
        return std::tuple<bool, const uint256&>(a.IsWtxid(), a.ToUint256()) <=> std::tuple<bool, const uint256&>(b.IsWtxid(), b.ToUint256());
83
717k
    }
84
};
85
86
#endif // BITCOIN_PRIMITIVES_TRANSACTION_IDENTIFIER_H