• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 15078892484

16 May 2025 11:04PM UTC coverage: 81.885% (-0.3%) from 82.18%
15078892484

push

github

web-flow
Merge pull request #1673 from evoskuil/master

Refactor all signature_hash methods to return bool (tapscript).

293 of 491 new or added lines in 17 files covered. (59.67%)

5 existing lines in 3 files now uncovered.

10365 of 12658 relevant lines covered (81.88%)

3781254.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.96
/src/chain/transaction_cache.cpp
1
/**
2
 * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/chain/transaction.hpp>
20

21
#include <iterator>
22
#include <bitcoin/system/chain/enums/coverage.hpp>
23
#include <bitcoin/system/chain/enums/extension.hpp>
24
#include <bitcoin/system/chain/enums/key_version.hpp>
25
#include <bitcoin/system/chain/input.hpp>
26
#include <bitcoin/system/chain/output.hpp>
27
#include <bitcoin/system/chain/script.hpp>
28
#include <bitcoin/system/data/data.hpp>
29
#include <bitcoin/system/endian/endian.hpp>
30
#include <bitcoin/system/define.hpp>
31
#include <bitcoin/system/error/error.hpp>
32
#include <bitcoin/system/hash/hash.hpp>
33
#include <bitcoin/system/math/math.hpp>
34
#include <bitcoin/system/stream/stream.hpp>
35

36
namespace libbitcoin {
37
namespace system {
38
namespace chain {
39

40
void transaction::initialize_sighash_cache() const NOEXCEPT
2✔
41
{
42
    if (!segregated_)
2✔
43
        return;
44

45
    // This overconstructs the cache (anyone or !all), however it is simple.
46
    sighash_cache_ =
2✔
47
    {
48
        hash_points(),
2✔
49
        hash_sequences(),
2✔
50
        hash_outputs()
2✔
51
    };
2✔
52
}
53

54
hash_digest transaction::hash_points() const NOEXCEPT
11✔
55
{
56
    if (sighash_cache_)
11✔
NEW
57
        return sighash_cache_->points;
×
58

59
    static hash_digest digest{};
11✔
60
    stream::out::fast stream{ digest };
11✔
61
    hash::sha256x2::fast sink{ stream };
11✔
62

63
    for (const auto& input: *inputs_)
27✔
64
        input->point().to_data(sink);
16✔
65

66
    sink.flush();
11✔
67
    return digest;
11✔
68
}
11✔
69

70
hash_digest transaction::hash_sequences() const NOEXCEPT
7✔
71
{
72
    if (sighash_cache_)
7✔
NEW
73
        return sighash_cache_->sequences;
×
74

75
    static hash_digest digest{};
7✔
76
    stream::out::fast stream{ digest };
7✔
77
    hash::sha256x2::fast sink{ stream };
7✔
78

79
    for (const auto& input: *inputs_)
17✔
80
        sink.write_4_bytes_little_endian(input->sequence());
10✔
81

82
    sink.flush();
7✔
83
    return digest;
7✔
84
}
7✔
85

86
hash_digest transaction::hash_outputs() const NOEXCEPT
8✔
87
{
88
    if (sighash_cache_)
8✔
NEW
89
        return sighash_cache_->outputs;
×
90

91
    static hash_digest digest{};
8✔
92
    stream::out::fast stream{ digest };
8✔
93
    hash::sha256x2::fast sink{ stream };
8✔
94

95
    for (const auto& output : *outputs_)
22✔
96
        output->to_data(sink);
14✔
97

98
    sink.flush();
8✔
99
    return digest;
8✔
100
}
8✔
101

102
// Cached identity hashing.
103
// ----------------------------------------------------------------------------
104

105
// static
106
// Compute the desegregated hash from a segregated buffer (used by network).
NEW
107
hash_digest transaction::desegregated_hash(size_t witnessed,
×
108
    size_t unwitnessed, const uint8_t* data) NOEXCEPT
109
{
NEW
110
    if (is_null(data))
×
NEW
111
        return null_hash;
×
112

NEW
113
    constexpr auto preamble = sizeof(uint32_t) + two * sizeof(uint8_t);
×
NEW
114
    const auto puts = floored_subtract(unwitnessed, two * sizeof(uint32_t));
×
NEW
115
    const auto locktime = floored_subtract(witnessed, sizeof(uint32_t));
×
116

NEW
117
    hash_digest digest{};
×
NEW
118
    stream::out::fast stream{ digest };
×
NEW
119
    hash::sha256x2::fast sink{ stream };
×
NEW
120
    sink.write_bytes(data, sizeof(uint32_t));
×
NEW
121
    sink.write_bytes(std::next(data, preamble), puts);
×
NEW
122
    sink.write_bytes(std::next(data, locktime), sizeof(uint32_t));
×
NEW
123
    sink.flush();
×
NEW
124
    return digest;
×
NEW
125
}
×
126

127
// Used to populate nominal hash after wire deserialization and store read.
128
void transaction::set_nominal_hash(const hash_digest& hash) const NOEXCEPT
20✔
129
{
130
    nominal_hash_ = hash;
20✔
131
}
1✔
132

133
// Used to populate witness hash after wire deserialization (not stored).
134
void transaction::set_witness_hash(const hash_digest& hash) const NOEXCEPT
2✔
135
{
136
    witness_hash_ = hash;
2✔
137
}
1✔
138

139
// More efficient than hash(bool) but not thead safe unless cached.
140
const hash_digest& transaction::get_hash(bool witness) const NOEXCEPT
26✔
141
{
142
    if (witness)
26✔
143
    {
144
        if (!witness_hash_) set_witness_hash(hash(witness));
4✔
145
        return *witness_hash_;
3✔
146
    }
147
    else
148
    {
149
        if (!nominal_hash_) set_nominal_hash(hash(witness));
42✔
150
        return *nominal_hash_;
23✔
151
    }
152
}
153

154
// Canonical form (thread safe).
155
hash_digest transaction::hash(bool witness) const NOEXCEPT
934✔
156
{
157
    if (segregated_)
934✔
158
    {
159
        if (witness)
23✔
160
        {
161
            // Witness coinbase tx hash is assumed to be null_hash [bip141].
NEW
162
            if (witness_hash_) return *witness_hash_;
×
NEW
163
            if (is_coinbase()) return null_hash;
×
164
        }
165
        else
166
        {
167
            if (nominal_hash_) return *nominal_hash_;
23✔
168
        }
169
    }
170
    else
171
    {
172
        if (nominal_hash_) return *nominal_hash_;
911✔
173
    }
174

175
    hash_digest digest{};
927✔
176
    stream::out::fast stream{ digest };
927✔
177
    hash::sha256x2::fast sink{ stream };
927✔
178
    to_data(sink, witness);
927✔
179
    sink.flush();
927✔
180
    return digest;
927✔
181
}
927✔
182

183
// Cached for signature hashing (not thead safe unless cached).
184
// ----------------------------------------------------------------------------
185
// These rarely overconstruct the cache (anyone or !all) and are simple.
186

187
////void transaction::initialize_sighash_cache() const NOEXCEPT
188
////{
189
////    initialize_v0_cache();
190
////    initialize_v1_cache();
191
////}
192

NEW
193
void transaction::initialize_v0_cache() const NOEXCEPT
×
194
{
195
    ////v0_cache_ = make_shared<v0_cache>(
196
    ////    double_hash_points(),
197
    ////    double_hash_sequences(),
198
    ////    double_hash_outputs());
NEW
199
}
×
200

NEW
201
void transaction::initialize_v1_cache() const NOEXCEPT
×
202
{
203
    ////v1_cache_ = make_shared<v1_cache>(
204
    ////    single_hash_amounts(),
205
    ////    single_hash_scripts(),
206
    ////    single_hash_points(),
207
    ////    single_hash_sequences(),
208
    ////    single_hash_outputs());
NEW
209
}
×
210

211
// sha256x1
212

NEW
213
const hash_digest& transaction::single_hash_points() const NOEXCEPT
×
214
{
215
    // TODO: if cache not computed, compute and then return from cache.
NEW
216
    static constexpr hash_digest hash{};
×
NEW
217
    return hash;
×
218
}
219

NEW
220
const hash_digest& transaction::single_hash_amounts() const NOEXCEPT
×
221
{
NEW
222
    static constexpr hash_digest hash{};
×
NEW
223
    return hash;
×
224
}
225

NEW
226
const hash_digest& transaction::single_hash_scripts() const NOEXCEPT
×
227
{
NEW
228
    static constexpr hash_digest hash{};
×
NEW
229
    return hash;
×
230
}
231

NEW
232
const hash_digest& transaction::single_hash_sequences() const NOEXCEPT
×
233
{
NEW
234
    static constexpr hash_digest hash{};
×
NEW
235
    return hash;
×
236
}
237

NEW
238
const hash_digest& transaction::single_hash_outputs() const NOEXCEPT
×
239
{
NEW
240
    static constexpr hash_digest hash{};
×
NEW
241
    return hash;
×
242
}
243

244
// sha256x2
245

NEW
246
const hash_digest& transaction::double_hash_points() const NOEXCEPT
×
247
{
248
    // TODO: if cache not computed, compute and then return from cache.
249
    // TODO: compute single hashes if not computed.
NEW
250
    static constexpr hash_digest hash{};
×
NEW
251
    return hash;
×
252
}
253

NEW
254
const hash_digest& transaction::double_hash_sequences() const NOEXCEPT
×
255
{
NEW
256
    static constexpr hash_digest hash{};
×
NEW
257
    return hash;
×
258
}
259

NEW
260
const hash_digest& transaction::double_hash_outputs() const NOEXCEPT
×
261
{
NEW
262
    static constexpr hash_digest hash{};
×
NEW
263
    return hash;
×
264
}
265

266
} // namespace chain
267
} // namespace system
268
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc