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

libbitcoin / libbitcoin-blockchain / 8117832118

01 Mar 2024 10:15PM CUT coverage: 37.046%. Remained the same
8117832118

push

github

web-flow
Merge pull request #554 from pmienk/version3

Regenerate artifacts.

592 of 1598 relevant lines covered (37.05%)

11.49 hits per line

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

20.69
/src/validate/validate_transaction.cpp
1
/**
2
 * Copyright (c) 2011-2023 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/blockchain/validate/validate_transaction.hpp>
20

21
#include <algorithm>
22
#include <atomic>
23
#include <cstddef>
24
#include <cstdint>
25
#include <functional>
26
#include <memory>
27
#include <bitcoin/system.hpp>
28
#include <bitcoin/blockchain/interface/fast_chain.hpp>
29
#include <bitcoin/blockchain/pools/branch.hpp>
30
#include <bitcoin/blockchain/settings.hpp>
31
#include <bitcoin/blockchain/validate/validate_input.hpp>
32

33
namespace libbitcoin {
34
namespace blockchain {
35

36
using namespace bc::chain;
37
using namespace bc::machine;
38
using namespace std::placeholders;
39

40
#define NAME "validate_transaction"
41

42
// Database access is limited to: populator:
43
// spend: { spender }
44
// transaction: { exists, height, output }
45

46
validate_transaction::validate_transaction(dispatcher& dispatch,
43✔
47
    const fast_chain& chain, const settings& settings)
43✔
48
  : stopped_(true),
49
    retarget_(settings.retarget),
43✔
50
    use_libconsensus_(settings.use_libconsensus),
43✔
51
    dispatch_(dispatch),
52
    transaction_populator_(dispatch, chain),
53
    fast_chain_(chain)
43✔
54
{
55
}
43✔
56

57
// Start/stop sequences.
58
//-----------------------------------------------------------------------------
59

60
void validate_transaction::start()
42✔
61
{
62
    stopped_ = false;
42✔
63
}
42✔
64

65
void validate_transaction::stop()
43✔
66
{
67
    stopped_ = true;
43✔
68
}
43✔
69

70
// Check.
71
//-----------------------------------------------------------------------------
72
// These checks are context free.
73

74
void validate_transaction::check(transaction_const_ptr tx,
×
75
    result_handler handler) const
76
{
77
    // Run context free checks.
78
    handler(tx->check(true, retarget_));
×
79
}
×
80

81
// Accept sequence.
82
//-----------------------------------------------------------------------------
83
// These checks require chain and tx state (net height and enabled forks).
84

85
void validate_transaction::accept(transaction_const_ptr tx,
×
86
    result_handler handler) const
87
{
88
    // Populate chain state of the next block (tx pool).
89
    tx->validation.state = fast_chain_.chain_state();
×
90

91
    if (!tx->validation.state)
×
92
    {
93
        handler(error::operation_failed);
×
94
        return;
×
95
    }
96

97
    transaction_populator_.populate(tx,
×
98
        std::bind(&validate_transaction::handle_populated,
×
99
            this, _1, tx, handler));
100
}
101

102
void validate_transaction::handle_populated(const code& ec,
×
103
    transaction_const_ptr tx, result_handler handler) const
104
{
105
    if (stopped())
×
106
    {
107
        handler(error::service_stopped);
×
108
        return;
×
109
    }
110

111
    if (ec)
×
112
    {
113
        handler(ec);
×
114
        return;
×
115
    }
116

117
    BITCOIN_ASSERT(tx->validation.state);
×
118

119
    // Run contextual tx checks.
120
    handler(tx->accept());
×
121
}
122

123
// Connect sequence.
124
//-----------------------------------------------------------------------------
125
// These checks require chain state, block state and perform script validation.
126

127
void validate_transaction::connect(transaction_const_ptr tx,
×
128
    result_handler handler) const
129
{
130
    BITCOIN_ASSERT(tx->validation.state);
×
131
    const auto total_inputs = tx->inputs().size();
×
132

133
    // Return if there are no inputs to validate (will fail later).
134
    if (total_inputs == 0)
×
135
    {
136
        handler(error::success);
×
137
        return;
×
138
    }
139

140
    const auto buckets = std::min(dispatch_.size(), total_inputs);
×
141
    const auto join_handler = synchronize(handler, buckets, NAME "_validate");
×
142
    BITCOIN_ASSERT(buckets != 0);
×
143

144
    // If the priority threadpool is shut down when this is called the handler
145
    // will never be invoked, resulting in a threadpool.join indefinite hang.
146
    for (size_t bucket = 0; bucket < buckets; ++bucket)
×
147
        dispatch_.concurrent(&validate_transaction::connect_inputs,
×
148
            this, tx, bucket, buckets, join_handler);
149
}
150

151
void validate_transaction::connect_inputs(transaction_const_ptr tx,
×
152
    size_t bucket, size_t buckets, result_handler handler) const
153
{
154
    BITCOIN_ASSERT(bucket < buckets);
×
155
    code ec(error::success);
×
156
    const auto forks = tx->validation.state->enabled_forks();
×
157
    const auto& inputs = tx->inputs();
×
158

159
    for (auto input_index = bucket; input_index < inputs.size();
×
160
        input_index = ceiling_add(input_index, buckets))
×
161
    {
162
        if (stopped())
×
163
        {
164
            ec = error::service_stopped;
×
165
            break;
166
        }
167

168
        const auto& prevout = inputs[input_index].previous_output();
×
169

170
        if (!prevout.validation.cache.is_valid())
×
171
        {
172
            ec = error::missing_previous_output;
×
173
            break;
174
        }
175

176
        if ((ec = validate_input::verify_script(*tx, input_index, forks,
×
177
            use_libconsensus_)))
×
178
        {
179
            break;
180
        }
181
    }
182

183
    handler(ec);
×
184
}
×
185

186
} // namespace blockchain
187
} // 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

© 2025 Coveralls, Inc