Branch data Line data Source code
1 : : // Copyright (c) 2022-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #define BITCOINKERNEL_BUILD
6 : :
7 : : #include <kernel/bitcoinkernel.h>
8 : :
9 : : #include <chain.h>
10 : : #include <coins.h>
11 : : #include <consensus/tx_check.h>
12 : : #include <consensus/validation.h>
13 : : #include <dbwrapper.h>
14 : : #include <kernel/caches.h>
15 : : #include <kernel/chainparams.h>
16 : : #include <kernel/checks.h>
17 : : #include <kernel/context.h>
18 : : #include <kernel/notifications_interface.h>
19 : : #include <kernel/warning.h>
20 : : #include <logging.h>
21 : : #include <node/blockstorage.h>
22 : : #include <node/chainstate.h>
23 : : #include <primitives/block.h>
24 : : #include <primitives/transaction.h>
25 : : #include <script/interpreter.h>
26 : : #include <script/script.h>
27 : : #include <script/verify_flags.h>
28 : : #include <serialize.h>
29 : : #include <streams.h>
30 : : #include <sync.h>
31 : : #include <uint256.h>
32 : : #include <undo.h>
33 : : #include <util/check.h>
34 : : #include <util/fs.h>
35 : : #include <util/result.h>
36 : : #include <util/signalinterrupt.h>
37 : : #include <util/task_runner.h>
38 : : #include <util/time.h>
39 : : #include <util/translation.h>
40 : : #include <validation.h>
41 : : #include <validationinterface.h>
42 : :
43 : : #include <cstddef>
44 : : #include <cstring>
45 : : #include <exception>
46 : : #include <functional>
47 : : #include <limits>
48 : : #include <list>
49 : : #include <memory>
50 : : #include <optional>
51 : : #include <span>
52 : : #include <stdexcept>
53 : : #include <string>
54 : : #include <tuple>
55 : : #include <utility>
56 : : #include <vector>
57 : :
58 : : namespace Consensus {
59 : : struct Params;
60 : : } // namespace Consensus
61 : :
62 : : using kernel::ChainstateRole;
63 : : using util::ImmediateTaskRunner;
64 : :
65 : : // Define G_TRANSLATION_FUN symbol in libbitcoinkernel library so users of the
66 : : // library aren't required to export this symbol
67 : : extern const TranslateFn G_TRANSLATION_FUN{nullptr};
68 : :
69 : : static const kernel::Context btck_context_static{};
70 : :
71 : : namespace {
72 : :
73 : 80 : bool is_valid_flag_combination(script_verify_flags flags)
74 : : {
75 [ - + - - ]: 80 : if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
76 [ + + - + ]: 80 : if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false;
77 : : return true;
78 : : }
79 : :
80 : : class WriterStream
81 : : {
82 : : private:
83 : : btck_WriteBytes m_writer;
84 : : void* m_user_data;
85 : :
86 : : public:
87 : 36 : WriterStream(btck_WriteBytes writer, void* user_data)
88 : 36 : : m_writer{writer}, m_user_data{user_data} {}
89 : :
90 : : //
91 : : // Stream subset
92 : : //
93 : 822 : void write(std::span<const std::byte> src)
94 : : {
95 [ - + ]: 822 : if (m_writer(src.data(), src.size(), m_user_data) != 0) {
96 [ # # ]: 0 : throw std::runtime_error("Failed to write serialization data");
97 : : }
98 : 822 : }
99 : :
100 : : template <typename T>
101 : 36 : WriterStream& operator<<(const T& obj)
102 : : {
103 [ + - + - ]: 36 : ::Serialize(*this, obj);
104 : 36 : return *this;
105 : : }
106 : : };
107 : :
108 : : template <typename C, typename CPP>
109 : : struct Handle {
110 : : static C* ref(CPP* cpp_type)
111 : : {
112 : : return reinterpret_cast<C*>(cpp_type);
113 : : }
114 : :
115 : : static const C* ref(const CPP* cpp_type)
116 : : {
117 : : return reinterpret_cast<const C*>(cpp_type);
118 : : }
119 : :
120 : : template <typename... Args>
121 : 8728 : static C* create(Args&&... args)
122 : : {
123 : 8728 : auto cpp_obj{std::make_unique<CPP>(std::forward<Args>(args)...)};
124 : 17456 : return ref(cpp_obj.release());
125 : 8728 : }
126 : :
127 : 815 : static C* copy(const C* ptr)
128 : : {
129 : 815 : auto cpp_obj{std::make_unique<CPP>(get(ptr))};
130 : 1630 : return ref(cpp_obj.release());
131 : 815 : }
132 : :
133 : : static const CPP& get(const C* ptr)
134 : : {
135 : : return *reinterpret_cast<const CPP*>(ptr);
136 : : }
137 : :
138 : : static CPP& get(C* ptr)
139 : : {
140 : : return *reinterpret_cast<CPP*>(ptr);
141 : : }
142 : :
143 : 9560 : static void operator delete(void* ptr)
144 : : {
145 [ + - ]: 17986 : delete reinterpret_cast<CPP*>(ptr);
146 : 9560 : }
147 : : };
148 : :
149 : : } // namespace
150 : :
151 : : struct btck_BlockTreeEntry: Handle<btck_BlockTreeEntry, CBlockIndex> {};
152 : : struct btck_Block : Handle<btck_Block, std::shared_ptr<const CBlock>> {};
153 : : struct btck_BlockValidationState : Handle<btck_BlockValidationState, BlockValidationState> {};
154 : : struct btck_TxValidationState : Handle<btck_TxValidationState, TxValidationState> {};
155 : :
156 : : namespace {
157 : :
158 : 2 : BCLog::Level get_bclog_level(btck_LogLevel level)
159 : : {
160 [ - + - - ]: 2 : switch (level) {
161 : : case btck_LogLevel_INFO: {
162 : : return BCLog::Level::Info;
163 : : }
164 : 0 : case btck_LogLevel_DEBUG: {
165 : 0 : return BCLog::Level::Debug;
166 : : }
167 : 2 : case btck_LogLevel_TRACE: {
168 : 2 : return BCLog::Level::Trace;
169 : : }
170 : : }
171 : 0 : assert(false);
172 : : }
173 : :
174 : 6 : BCLog::LogFlags get_bclog_flag(btck_LogCategory category)
175 : : {
176 [ - - - - : 6 : switch (category) {
- - - + +
- - + ]
177 : : case btck_LogCategory_BENCH: {
178 : : return BCLog::LogFlags::BENCH;
179 : : }
180 : 0 : case btck_LogCategory_BLOCKSTORAGE: {
181 : 0 : return BCLog::LogFlags::BLOCKSTORAGE;
182 : : }
183 : 0 : case btck_LogCategory_COINDB: {
184 : 0 : return BCLog::LogFlags::COINDB;
185 : : }
186 : 0 : case btck_LogCategory_LEVELDB: {
187 : 0 : return BCLog::LogFlags::LEVELDB;
188 : : }
189 : 0 : case btck_LogCategory_MEMPOOL: {
190 : 0 : return BCLog::LogFlags::MEMPOOL;
191 : : }
192 : 0 : case btck_LogCategory_PRUNE: {
193 : 0 : return BCLog::LogFlags::PRUNE;
194 : : }
195 : 0 : case btck_LogCategory_RAND: {
196 : 0 : return BCLog::LogFlags::RAND;
197 : : }
198 : 0 : case btck_LogCategory_REINDEX: {
199 : 0 : return BCLog::LogFlags::REINDEX;
200 : : }
201 : 2 : case btck_LogCategory_VALIDATION: {
202 : 2 : return BCLog::LogFlags::VALIDATION;
203 : : }
204 : 2 : case btck_LogCategory_KERNEL: {
205 : 2 : return BCLog::LogFlags::KERNEL;
206 : : }
207 : 0 : case btck_LogCategory_ALL: {
208 : 0 : return BCLog::LogFlags::ALL;
209 : : }
210 : : }
211 : 0 : assert(false);
212 : : }
213 : :
214 : 849 : btck_SynchronizationState cast_state(SynchronizationState state)
215 : : {
216 [ + - - + ]: 849 : switch (state) {
217 : : case SynchronizationState::INIT_REINDEX:
218 : : return btck_SynchronizationState_INIT_REINDEX;
219 : 846 : case SynchronizationState::INIT_DOWNLOAD:
220 : 846 : return btck_SynchronizationState_INIT_DOWNLOAD;
221 : 0 : case SynchronizationState::POST_INIT:
222 : 0 : return btck_SynchronizationState_POST_INIT;
223 : : } // no default case, so the compiler can warn about missing cases
224 : 0 : assert(false);
225 : : }
226 : :
227 : 428 : btck_Warning cast_btck_warning(kernel::Warning warning)
228 : : {
229 [ + - - ]: 428 : switch (warning) {
230 : : case kernel::Warning::UNKNOWN_NEW_RULES_ACTIVATED:
231 : : return btck_Warning_UNKNOWN_NEW_RULES_ACTIVATED;
232 : 428 : case kernel::Warning::LARGE_WORK_INVALID_CHAIN:
233 : 428 : return btck_Warning_LARGE_WORK_INVALID_CHAIN;
234 : : } // no default case, so the compiler can warn about missing cases
235 : 0 : assert(false);
236 : : }
237 : :
238 : : struct LoggingConnection {
239 : : std::unique_ptr<std::list<std::function<void(const std::string&)>>::iterator> m_connection;
240 : : void* m_user_data;
241 : : std::function<void(void* user_data)> m_deleter;
242 : :
243 : 4 : LoggingConnection(btck_LogCallback callback, void* user_data, btck_DestroyCallback user_data_destroy_callback)
244 [ + - ]: 4 : {
245 [ + - ]: 4 : LOCK(cs_main);
246 : :
247 [ - + + - : 129 : auto connection{LogInstance().PushBackCallback([callback, user_data](const std::string& str) { callback(user_data, str.c_str(), str.length()); })};
+ - ]
248 : :
249 : : // Only start logging if we just added the connection.
250 [ + - + - : 4 : if (LogInstance().NumConnections() == 1 && !LogInstance().StartLogging()) {
+ + + - +
- - + ]
251 [ # # ]: 0 : LogError("Logger start failed.");
252 [ # # # # ]: 0 : LogInstance().DeleteCallback(connection);
253 [ # # # # ]: 0 : if (user_data && user_data_destroy_callback) {
254 [ # # ]: 0 : user_data_destroy_callback(user_data);
255 : : }
256 [ # # ]: 0 : throw std::runtime_error("Failed to start logging");
257 : : }
258 : :
259 [ + - ]: 4 : m_connection = std::make_unique<std::list<std::function<void(const std::string&)>>::iterator>(connection);
260 : 4 : m_user_data = user_data;
261 : 4 : m_deleter = user_data_destroy_callback;
262 : :
263 [ + - + - : 4 : LogDebug(BCLog::KERNEL, "Logger connected.");
+ - + - ]
264 : 4 : }
265 : :
266 : 4 : ~LoggingConnection()
267 : : {
268 : 4 : LOCK(cs_main);
269 [ + - ]: 4 : LogDebug(BCLog::KERNEL, "Logger disconnecting.");
270 : :
271 : : // Switch back to buffering by calling DisconnectTestLogger if the
272 : : // connection that we are about to remove is the last one.
273 [ + + ]: 4 : if (LogInstance().NumConnections() == 1) {
274 : 3 : LogInstance().DisconnectTestLogger();
275 : : } else {
276 : 1 : LogInstance().DeleteCallback(*m_connection);
277 : : }
278 : :
279 [ + - ]: 4 : m_connection.reset();
280 [ + - + - ]: 4 : if (m_user_data && m_deleter) {
281 : 4 : m_deleter(m_user_data);
282 : : }
283 : 4 : }
284 : : };
285 : :
286 : : class KernelNotifications final : public kernel::Notifications
287 : : {
288 : : private:
289 : : btck_NotificationInterfaceCallbacks m_cbs;
290 : :
291 : : public:
292 : 15 : KernelNotifications(btck_NotificationInterfaceCallbacks cbs)
293 : 15 : : m_cbs{cbs}
294 : : {
295 : : }
296 : :
297 : 15 : ~KernelNotifications()
298 : 15 : {
299 [ + + + - ]: 15 : if (m_cbs.user_data && m_cbs.user_data_destroy) {
300 : 9 : m_cbs.user_data_destroy(m_cbs.user_data);
301 : : }
302 : 15 : m_cbs.user_data_destroy = nullptr;
303 : 15 : m_cbs.user_data = nullptr;
304 : 15 : }
305 : :
306 : 430 : kernel::InterruptResult blockTip(SynchronizationState state, const CBlockIndex& index, double verification_progress) override
307 : : {
308 [ + + ]: 430 : if (m_cbs.block_tip) m_cbs.block_tip(m_cbs.user_data, cast_state(state), btck_BlockTreeEntry::ref(&index), verification_progress);
309 : 430 : return {};
310 : : }
311 : 421 : void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override
312 : : {
313 [ + - + - ]: 842 : if (m_cbs.header_tip) m_cbs.header_tip(m_cbs.user_data, cast_state(state), height, timestamp, presync ? 1 : 0);
314 : 421 : }
315 : 15 : void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override
316 : : {
317 [ + + + - : 28 : if (m_cbs.progress) m_cbs.progress(m_cbs.user_data, title.original.c_str(), title.original.length(), progress_percent, resume_possible ? 1 : 0);
- + ]
318 : 15 : }
319 : 0 : void warningSet(kernel::Warning id, const bilingual_str& message) override
320 : : {
321 [ # # # # ]: 0 : if (m_cbs.warning_set) m_cbs.warning_set(m_cbs.user_data, cast_btck_warning(id), message.original.c_str(), message.original.length());
322 : 0 : }
323 : 430 : void warningUnset(kernel::Warning id) override
324 : : {
325 [ + + ]: 430 : if (m_cbs.warning_unset) m_cbs.warning_unset(m_cbs.user_data, cast_btck_warning(id));
326 : 430 : }
327 : 0 : void flushError(const bilingual_str& message) override
328 : : {
329 [ # # # # ]: 0 : if (m_cbs.flush_error) m_cbs.flush_error(m_cbs.user_data, message.original.c_str(), message.original.length());
330 : 0 : }
331 : 0 : void fatalError(const bilingual_str& message) override
332 : : {
333 [ # # # # ]: 0 : if (m_cbs.fatal_error) m_cbs.fatal_error(m_cbs.user_data, message.original.c_str(), message.original.length());
334 : 0 : }
335 : : };
336 : :
337 : : class KernelValidationInterface final : public CValidationInterface
338 : : {
339 : : public:
340 : : btck_ValidationInterfaceCallbacks m_cbs;
341 : :
342 : 1 : explicit KernelValidationInterface(const btck_ValidationInterfaceCallbacks vi_cbs) : m_cbs{vi_cbs} {}
343 : :
344 : 1 : ~KernelValidationInterface()
345 : 1 : {
346 [ + - + - ]: 1 : if (m_cbs.user_data && m_cbs.user_data_destroy) {
347 : 1 : m_cbs.user_data_destroy(m_cbs.user_data);
348 : : }
349 : 1 : m_cbs.user_data = nullptr;
350 : 1 : m_cbs.user_data_destroy = nullptr;
351 : 1 : }
352 : :
353 : : protected:
354 : 3 : void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& stateIn) override
355 : : {
356 [ + - ]: 3 : if (m_cbs.block_checked) {
357 : 3 : m_cbs.block_checked(m_cbs.user_data,
358 : : btck_Block::copy(btck_Block::ref(&block)),
359 : : btck_BlockValidationState::ref(&stateIn));
360 : : }
361 : 3 : }
362 : :
363 : 0 : void NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block) override
364 : : {
365 [ # # ]: 0 : if (m_cbs.pow_valid_block) {
366 : 0 : m_cbs.pow_valid_block(m_cbs.user_data,
367 : : btck_Block::copy(btck_Block::ref(&block)),
368 : : btck_BlockTreeEntry::ref(pindex));
369 : : }
370 : 0 : }
371 : :
372 : 2 : void BlockConnected(const ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override
373 : : {
374 [ + - ]: 2 : if (m_cbs.block_connected) {
375 : 2 : m_cbs.block_connected(m_cbs.user_data,
376 : : btck_Block::copy(btck_Block::ref(&block)),
377 : : btck_BlockTreeEntry::ref(pindex));
378 : : }
379 : 2 : }
380 : :
381 : 0 : void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override
382 : : {
383 [ # # ]: 0 : if (m_cbs.block_disconnected) {
384 : 0 : m_cbs.block_disconnected(m_cbs.user_data,
385 : : btck_Block::copy(btck_Block::ref(&block)),
386 : : btck_BlockTreeEntry::ref(pindex));
387 : : }
388 : 0 : }
389 : : };
390 : :
391 : 15 : struct ContextOptions {
392 : : mutable Mutex m_mutex;
393 : : std::unique_ptr<const CChainParams> m_chainparams GUARDED_BY(m_mutex);
394 : : std::shared_ptr<KernelNotifications> m_notifications GUARDED_BY(m_mutex);
395 : : std::shared_ptr<KernelValidationInterface> m_validation_interface GUARDED_BY(m_mutex);
396 : : };
397 : :
398 : : class Context
399 : : {
400 : : public:
401 : : std::unique_ptr<kernel::Context> m_context;
402 : :
403 : : std::shared_ptr<KernelNotifications> m_notifications;
404 : :
405 : : std::unique_ptr<util::SignalInterrupt> m_interrupt;
406 : :
407 : : std::unique_ptr<ValidationSignals> m_signals;
408 : :
409 : : std::unique_ptr<const CChainParams> m_chainparams;
410 : :
411 : : std::shared_ptr<KernelValidationInterface> m_validation_interface;
412 : :
413 : 15 : Context(const ContextOptions* options, bool& sane)
414 : 15 : : m_context{std::make_unique<kernel::Context>()},
415 [ + - + - ]: 15 : m_interrupt{std::make_unique<util::SignalInterrupt>()}
416 : : {
417 [ + - ]: 15 : if (options) {
418 [ + - ]: 15 : LOCK(options->m_mutex);
419 [ + + ]: 15 : if (options->m_chainparams) {
420 [ + - ]: 9 : m_chainparams = std::make_unique<const CChainParams>(*options->m_chainparams);
421 : : }
422 [ + + ]: 15 : if (options->m_notifications) {
423 : 9 : m_notifications = options->m_notifications;
424 : : }
425 [ + + ]: 15 : if (options->m_validation_interface) {
426 [ + - + - ]: 1 : m_signals = std::make_unique<ValidationSignals>(std::make_unique<ImmediateTaskRunner>());
427 : 1 : m_validation_interface = options->m_validation_interface;
428 [ + - + - ]: 3 : m_signals->RegisterSharedValidationInterface(m_validation_interface);
429 : : }
430 : 15 : }
431 : :
432 [ + + ]: 15 : if (!m_chainparams) {
433 [ + - ]: 6 : m_chainparams = CChainParams::Main();
434 : : }
435 [ + + ]: 15 : if (!m_notifications) {
436 [ + - ]: 12 : m_notifications = std::make_shared<KernelNotifications>(btck_NotificationInterfaceCallbacks{
437 [ - + ]: 6 : nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr});
438 : : }
439 : :
440 [ + - - + ]: 15 : if (!kernel::SanityChecks(*m_context)) {
441 : 0 : sane = false;
442 : : }
443 [ - - - - ]: 15 : }
444 : :
445 : 15 : ~Context()
446 : : {
447 [ + + ]: 15 : if (m_signals) {
448 [ + - + - ]: 3 : m_signals->UnregisterSharedValidationInterface(m_validation_interface);
449 : : }
450 [ + + + - ]: 31 : }
451 : : };
452 : :
453 : : //! Helper struct to wrap the ChainstateManager-related Options
454 : : struct ChainstateManagerOptions {
455 : : mutable Mutex m_mutex;
456 : : ChainstateManager::Options m_chainman_options GUARDED_BY(m_mutex);
457 : : node::BlockManager::Options m_blockman_options GUARDED_BY(m_mutex);
458 : : std::shared_ptr<const Context> m_context;
459 : : node::ChainstateLoadOptions m_chainstate_load_options GUARDED_BY(m_mutex);
460 : : uint64_t m_db_cache_bytes GUARDED_BY(m_mutex){DEFAULT_KERNEL_CACHE};
461 : :
462 : 12 : ChainstateManagerOptions(const std::shared_ptr<const Context>& context, const fs::path& data_dir, const fs::path& blocks_dir)
463 [ + - ]: 12 : : m_chainman_options{ChainstateManager::Options{
464 : 12 : .chainparams = *context->m_chainparams,
465 : : .datadir = data_dir,
466 [ + - ]: 12 : .notifications = *context->m_notifications,
467 [ + - ]: 12 : .signals = context->m_signals.get()}},
468 [ + - ]: 24 : m_blockman_options{node::BlockManager::Options{
469 [ + - ]: 12 : .chainparams = *context->m_chainparams,
470 : : .blocks_dir = blocks_dir,
471 [ + - ]: 12 : .notifications = *context->m_notifications,
472 : : .block_tree_db_params = DBParams{
473 [ + - + - ]: 36 : .path = data_dir / "blocks" / "index",
474 : 12 : .cache_bytes = kernel::CacheSizes{DEFAULT_KERNEL_CACHE}.block_tree_db,
475 : : }}},
476 [ + - ]: 36 : m_context{context}, m_chainstate_load_options{node::ChainstateLoadOptions{}}
477 : : {
478 : 12 : }
479 : : };
480 : :
481 : : struct ChainMan {
482 : : std::unique_ptr<ChainstateManager> m_chainman;
483 : : std::shared_ptr<const Context> m_context;
484 : :
485 : 12 : ChainMan(std::unique_ptr<ChainstateManager> chainman, std::shared_ptr<const Context> context)
486 : 12 : : m_chainman(std::move(chainman)), m_context(std::move(context)) {}
487 : : };
488 : :
489 : : } // namespace
490 : :
491 : : struct btck_Transaction : Handle<btck_Transaction, std::shared_ptr<const CTransaction>> {};
492 : : struct btck_TransactionOutput : Handle<btck_TransactionOutput, CTxOut> {};
493 : : struct btck_ScriptPubkey : Handle<btck_ScriptPubkey, CScript> {};
494 : : struct btck_LoggingConnection : Handle<btck_LoggingConnection, LoggingConnection> {};
495 : : struct btck_ContextOptions : Handle<btck_ContextOptions, ContextOptions> {};
496 : : struct btck_Context : Handle<btck_Context, std::shared_ptr<const Context>> {};
497 : : struct btck_ChainParameters : Handle<btck_ChainParameters, CChainParams> {};
498 : : struct btck_ChainstateManagerOptions : Handle<btck_ChainstateManagerOptions, ChainstateManagerOptions> {};
499 : : struct btck_ChainstateManager : Handle<btck_ChainstateManager, ChainMan> {};
500 : : struct btck_Chain : Handle<btck_Chain, CChain> {};
501 : : struct btck_BlockSpentOutputs : Handle<btck_BlockSpentOutputs, std::shared_ptr<CBlockUndo>> {};
502 : : struct btck_TransactionSpentOutputs : Handle<btck_TransactionSpentOutputs, CTxUndo> {};
503 : : struct btck_Coin : Handle<btck_Coin, Coin> {};
504 : : struct btck_BlockHash : Handle<btck_BlockHash, uint256> {};
505 : : struct btck_TransactionInput : Handle<btck_TransactionInput, CTxIn> {};
506 : : struct btck_WitnessStack : Handle<btck_WitnessStack, CScriptWitness> {};
507 : : struct btck_TransactionOutPoint: Handle<btck_TransactionOutPoint, COutPoint> {};
508 : : struct btck_Txid: Handle<btck_Txid, Txid> {};
509 : : struct btck_PrecomputedTransactionData : Handle<btck_PrecomputedTransactionData, PrecomputedTransactionData> {};
510 : : struct btck_BlockHeader: Handle<btck_BlockHeader, CBlockHeader> {};
511 : : struct btck_ConsensusParams: Handle<btck_ConsensusParams, Consensus::Params> {};
512 : :
513 : 27 : btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len)
514 : : {
515 [ - + ]: 27 : assert(raw_transaction != nullptr || raw_transaction_len == 0);
516 : 27 : try {
517 [ + + ]: 27 : SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_transaction), raw_transaction_len}};
518 [ + + + - : 27 : return btck_Transaction::create(std::make_shared<const CTransaction>(deserialize, TX_WITH_WITNESS, stream));
- + ]
519 : 3 : } catch (...) {
520 : 3 : return nullptr;
521 : 3 : }
522 : : }
523 : :
524 : 287 : size_t btck_transaction_count_outputs(const btck_Transaction* transaction)
525 : : {
526 [ - + ]: 287 : return btck_Transaction::get(transaction)->vout.size();
527 : : }
528 : :
529 : 601 : const btck_TransactionOutput* btck_transaction_get_output_at(const btck_Transaction* transaction, size_t output_index)
530 : : {
531 [ - + ]: 601 : const CTransaction& tx = *btck_Transaction::get(transaction);
532 [ - + - + ]: 601 : assert(output_index < tx.vout.size());
533 : 601 : return btck_TransactionOutput::ref(&tx.vout[output_index]);
534 : : }
535 : :
536 : 284 : size_t btck_transaction_count_inputs(const btck_Transaction* transaction)
537 : : {
538 [ - + ]: 284 : return btck_Transaction::get(transaction)->vin.size();
539 : : }
540 : :
541 : 282 : const btck_TransactionInput* btck_transaction_get_input_at(const btck_Transaction* transaction, size_t input_index)
542 : : {
543 [ - + - + ]: 282 : assert(input_index < btck_Transaction::get(transaction)->vin.size());
544 : 282 : return btck_TransactionInput::ref(&btck_Transaction::get(transaction)->vin[input_index]);
545 : : }
546 : :
547 : 1 : uint32_t btck_transaction_get_locktime(const btck_Transaction* transaction)
548 : : {
549 : 1 : return btck_Transaction::get(transaction)->nLockTime;
550 : : }
551 : :
552 : 7635 : const btck_Txid* btck_transaction_get_txid(const btck_Transaction* transaction)
553 : : {
554 : 7635 : return btck_Txid::ref(&btck_Transaction::get(transaction)->GetHash());
555 : : }
556 : :
557 : 384 : btck_Transaction* btck_transaction_copy(const btck_Transaction* transaction)
558 : : {
559 : 384 : return btck_Transaction::copy(transaction);
560 : : }
561 : :
562 : 14 : int btck_transaction_to_bytes(const btck_Transaction* transaction, btck_WriteBytes writer, void* user_data)
563 : : {
564 : 14 : try {
565 : 14 : WriterStream ws{writer, user_data};
566 [ + - ]: 28 : ws << TX_WITH_WITNESS(btck_Transaction::get(transaction));
567 : : return 0;
568 : 0 : } catch (...) {
569 : 0 : return -1;
570 : 0 : }
571 : : }
572 : :
573 : 469 : void btck_transaction_destroy(btck_Transaction* transaction)
574 : : {
575 [ + + ]: 469 : delete transaction;
576 : 469 : }
577 : :
578 : 11 : btck_ScriptPubkey* btck_script_pubkey_create(const void* script_pubkey, size_t script_pubkey_len)
579 : : {
580 [ - + ]: 11 : assert(script_pubkey != nullptr || script_pubkey_len == 0);
581 : 11 : auto data = std::span{reinterpret_cast<const uint8_t*>(script_pubkey), script_pubkey_len};
582 : 11 : return btck_ScriptPubkey::create(data.begin(), data.end());
583 : : }
584 : :
585 : 555 : int btck_script_pubkey_to_bytes(const btck_ScriptPubkey* script_pubkey_, btck_WriteBytes writer, void* user_data)
586 : : {
587 : 555 : const auto& script_pubkey{btck_ScriptPubkey::get(script_pubkey_)};
588 [ + + + + ]: 1317 : return writer(script_pubkey.data(), script_pubkey.size(), user_data);
589 : : }
590 : :
591 : 12 : btck_ScriptPubkey* btck_script_pubkey_copy(const btck_ScriptPubkey* script_pubkey)
592 : : {
593 : 12 : return btck_ScriptPubkey::copy(script_pubkey);
594 : : }
595 : :
596 : 27 : void btck_script_pubkey_destroy(btck_ScriptPubkey* script_pubkey)
597 : : {
598 [ + + ]: 27 : delete script_pubkey;
599 : 27 : }
600 : :
601 : 5 : btck_TransactionOutput* btck_transaction_output_create(const btck_ScriptPubkey* script_pubkey, int64_t amount)
602 : : {
603 : 5 : return btck_TransactionOutput::create(amount, btck_ScriptPubkey::get(script_pubkey));
604 : : }
605 : :
606 : 66 : btck_TransactionOutput* btck_transaction_output_copy(const btck_TransactionOutput* output)
607 : : {
608 : 66 : return btck_TransactionOutput::copy(output);
609 : : }
610 : :
611 : 585 : const btck_ScriptPubkey* btck_transaction_output_get_script_pubkey(const btck_TransactionOutput* output)
612 : : {
613 : 585 : return btck_ScriptPubkey::ref(&btck_TransactionOutput::get(output).scriptPubKey);
614 : : }
615 : :
616 : 388 : int64_t btck_transaction_output_get_amount(const btck_TransactionOutput* output)
617 : : {
618 : 388 : return btck_TransactionOutput::get(output).nValue;
619 : : }
620 : :
621 : 80 : void btck_transaction_output_destroy(btck_TransactionOutput* output)
622 : : {
623 [ + + ]: 80 : delete output;
624 : 80 : }
625 : :
626 : 266 : btck_PrecomputedTransactionData* btck_precomputed_transaction_data_create(
627 : : const btck_Transaction* tx_to,
628 : : const btck_TransactionOutput** spent_outputs_, size_t spent_outputs_len)
629 : : {
630 : 266 : try {
631 [ + - ]: 266 : const CTransaction& tx{*btck_Transaction::get(tx_to)};
632 [ + - ]: 266 : auto txdata{btck_PrecomputedTransactionData::create()};
633 [ + + ]: 266 : if (spent_outputs_ != nullptr && spent_outputs_len > 0) {
634 [ - + - + ]: 55 : assert(spent_outputs_len == tx.vin.size());
635 : 55 : std::vector<CTxOut> spent_outputs;
636 [ + - ]: 55 : spent_outputs.reserve(spent_outputs_len);
637 [ + + ]: 117 : for (size_t i = 0; i < spent_outputs_len; i++) {
638 : 62 : const CTxOut& tx_out{btck_TransactionOutput::get(spent_outputs_[i])};
639 [ + - ]: 62 : spent_outputs.push_back(tx_out);
640 : : }
641 [ + - ]: 55 : btck_PrecomputedTransactionData::get(txdata).Init(tx, std::move(spent_outputs));
642 : 55 : } else {
643 [ + - ]: 211 : btck_PrecomputedTransactionData::get(txdata).Init(tx, {});
644 : : }
645 : :
646 : : return txdata;
647 : 0 : } catch (...) {
648 : 0 : return nullptr;
649 : 0 : }
650 : : }
651 : :
652 : 5 : btck_PrecomputedTransactionData* btck_precomputed_transaction_data_copy(const btck_PrecomputedTransactionData* precomputed_txdata)
653 : : {
654 : 5 : return btck_PrecomputedTransactionData::copy(precomputed_txdata);
655 : : }
656 : :
657 : 273 : void btck_precomputed_transaction_data_destroy(btck_PrecomputedTransactionData* precomputed_txdata)
658 : : {
659 [ + + ]: 273 : delete precomputed_txdata;
660 : 273 : }
661 : :
662 : 80 : int btck_script_pubkey_verify(const btck_ScriptPubkey* script_pubkey,
663 : : const int64_t amount,
664 : : const btck_Transaction* tx_to,
665 : : const btck_PrecomputedTransactionData* precomputed_txdata,
666 : : const unsigned int input_index,
667 : : const btck_ScriptVerificationFlags flags,
668 : : btck_ScriptVerifyStatus* status)
669 : : {
670 : : // Assert that all specified flags are part of the interface before continuing
671 [ - + ]: 80 : assert((flags & ~btck_ScriptVerificationFlags_ALL) == 0);
672 : :
673 [ - + ]: 80 : if (!is_valid_flag_combination(script_verify_flags::from_int(flags))) {
674 [ # # ]: 0 : if (status) *status = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION;
675 : 0 : return 0;
676 : : }
677 : :
678 [ - + ]: 80 : const CTransaction& tx{*btck_Transaction::get(tx_to)};
679 [ - + - + ]: 80 : assert(input_index < tx.vin.size());
680 : :
681 [ + + ]: 80 : const PrecomputedTransactionData& txdata{precomputed_txdata ? btck_PrecomputedTransactionData::get(precomputed_txdata) : PrecomputedTransactionData(tx)};
682 : :
683 [ + + + + ]: 80 : if (flags & btck_ScriptVerificationFlags_TAPROOT && txdata.m_spent_outputs.empty()) {
684 [ + - ]: 4 : if (status) *status = btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED;
685 : 4 : return 0;
686 : : }
687 : :
688 [ + - ]: 76 : if (status) *status = btck_ScriptVerifyStatus_OK;
689 : :
690 [ + - ]: 76 : bool result = VerifyScript(tx.vin[input_index].scriptSig,
691 : : btck_ScriptPubkey::get(script_pubkey),
692 [ + - ]: 76 : &tx.vin[input_index].scriptWitness,
693 : : script_verify_flags::from_int(flags),
694 [ + - ]: 76 : TransactionSignatureChecker(&tx, input_index, amount, txdata, MissingDataBehavior::FAIL),
695 : : nullptr);
696 [ - + ]: 76 : return result ? 1 : 0;
697 : 80 : }
698 : :
699 : 66 : btck_TransactionInput* btck_transaction_input_copy(const btck_TransactionInput* input)
700 : : {
701 : 66 : return btck_TransactionInput::copy(input);
702 : : }
703 : :
704 : 268 : const btck_TransactionOutPoint* btck_transaction_input_get_out_point(const btck_TransactionInput* input)
705 : : {
706 : 268 : return btck_TransactionOutPoint::ref(&btck_TransactionInput::get(input).prevout);
707 : : }
708 : :
709 : 1 : uint32_t btck_transaction_input_get_sequence(const btck_TransactionInput* input)
710 : : {
711 : 1 : return btck_TransactionInput::get(input).nSequence;
712 : : }
713 : :
714 : 2 : const btck_WitnessStack* btck_transaction_input_get_witness_stack(const btck_TransactionInput* input)
715 : : {
716 : 2 : return btck_WitnessStack::ref(&btck_TransactionInput::get(input).scriptWitness);
717 : : }
718 : :
719 : 3 : int btck_transaction_input_get_script_sig(const btck_TransactionInput* input, btck_WriteBytes writer, void* user_data)
720 : : {
721 : 3 : const auto& script_sig{btck_TransactionInput::get(input).scriptSig};
722 [ + + + + ]: 8 : return writer(script_sig.data(), script_sig.size(), user_data);
723 : : }
724 : :
725 : 74 : void btck_transaction_input_destroy(btck_TransactionInput* input)
726 : : {
727 [ + + ]: 74 : delete input;
728 : 74 : }
729 : :
730 : 9 : size_t btck_witness_stack_count_items(const btck_WitnessStack* witness_stack)
731 : : {
732 [ - + ]: 9 : return btck_WitnessStack::get(witness_stack).stack.size();
733 : : }
734 : :
735 : 12 : int btck_witness_stack_get_item_at(const btck_WitnessStack* witness_stack, size_t index, btck_WriteBytes writer, void* user_data)
736 : : {
737 : 12 : const auto& stack{btck_WitnessStack::get(witness_stack).stack};
738 [ - + - + ]: 12 : assert(index < stack.size());
739 [ - + ]: 12 : return writer(stack[index].data(), stack[index].size(), user_data);
740 : : }
741 : :
742 : 7 : btck_WitnessStack* btck_witness_stack_copy(const btck_WitnessStack* witness_stack)
743 : : {
744 : 7 : return btck_WitnessStack::copy(witness_stack);
745 : : }
746 : :
747 : 9 : void btck_witness_stack_destroy(btck_WitnessStack* witness_stack)
748 : : {
749 [ + + ]: 9 : delete witness_stack;
750 : 9 : }
751 : :
752 : 7 : btck_TransactionOutPoint* btck_transaction_out_point_copy(const btck_TransactionOutPoint* out_point)
753 : : {
754 : 7 : return btck_TransactionOutPoint::copy(out_point);
755 : : }
756 : :
757 : 325 : uint32_t btck_transaction_out_point_get_index(const btck_TransactionOutPoint* out_point)
758 : : {
759 : 325 : return btck_TransactionOutPoint::get(out_point).n;
760 : : }
761 : :
762 : 177 : const btck_Txid* btck_transaction_out_point_get_txid(const btck_TransactionOutPoint* out_point)
763 : : {
764 : 177 : return btck_Txid::ref(&btck_TransactionOutPoint::get(out_point).hash);
765 : : }
766 : :
767 : 9 : void btck_transaction_out_point_destroy(btck_TransactionOutPoint* out_point)
768 : : {
769 [ + + ]: 9 : delete out_point;
770 : 9 : }
771 : :
772 : 7 : btck_Txid* btck_txid_copy(const btck_Txid* txid)
773 : : {
774 : 7 : return btck_Txid::copy(txid);
775 : : }
776 : :
777 : 13 : void btck_txid_to_bytes(const btck_Txid* txid, unsigned char output[32])
778 : : {
779 : 13 : std::memcpy(output, btck_Txid::get(txid).begin(), 32);
780 : 13 : }
781 : :
782 : 7633 : int btck_txid_equals(const btck_Txid* txid1, const btck_Txid* txid2)
783 : : {
784 [ + + ]: 7633 : return btck_Txid::get(txid1) == btck_Txid::get(txid2);
785 : : }
786 : :
787 : 9 : void btck_txid_destroy(btck_Txid* txid)
788 : : {
789 [ + + ]: 9 : delete txid;
790 : 9 : }
791 : :
792 : 1 : void btck_logging_set_options(const btck_LoggingOptions options)
793 : : {
794 : 1 : LOCK(cs_main);
795 [ + - ]: 1 : LogInstance().m_log_timestamps = options.log_timestamps;
796 [ + - ]: 1 : LogInstance().m_log_time_micros = options.log_time_micros;
797 [ + - ]: 1 : LogInstance().m_log_threadnames = options.log_threadnames;
798 [ + - ]: 1 : LogInstance().m_log_sourcelocations = options.log_sourcelocations;
799 [ + - + - ]: 1 : LogInstance().m_always_print_category_level = options.always_print_category_levels;
800 : 1 : }
801 : :
802 : 2 : void btck_logging_set_level_category(btck_LogCategory category, btck_LogLevel level)
803 : : {
804 : 2 : LOCK(cs_main);
805 [ - + ]: 2 : if (category == btck_LogCategory_ALL) {
806 [ # # ]: 0 : LogInstance().SetLogLevel(get_bclog_level(level));
807 : : }
808 : :
809 [ + - + - ]: 2 : LogInstance().AddCategoryLogLevel(get_bclog_flag(category), get_bclog_level(level));
810 : 2 : }
811 : :
812 : 2 : void btck_logging_enable_category(btck_LogCategory category)
813 : : {
814 : 2 : LogInstance().EnableCategory(get_bclog_flag(category));
815 : 2 : }
816 : :
817 : 2 : void btck_logging_disable_category(btck_LogCategory category)
818 : : {
819 : 2 : LogInstance().DisableCategory(get_bclog_flag(category));
820 : 2 : }
821 : :
822 : 0 : void btck_logging_disable()
823 : : {
824 : 0 : LogInstance().DisableLogging();
825 : 0 : }
826 : :
827 : 4 : btck_LoggingConnection* btck_logging_connection_create(btck_LogCallback callback, void* user_data, btck_DestroyCallback user_data_destroy_callback)
828 : : {
829 : 4 : try {
830 [ + - ]: 4 : return btck_LoggingConnection::create(callback, user_data, user_data_destroy_callback);
831 [ - - ]: 0 : } catch (const std::exception&) {
832 : 0 : return nullptr;
833 : 0 : }
834 : : }
835 : :
836 : 4 : void btck_logging_connection_destroy(btck_LoggingConnection* connection)
837 : : {
838 [ + - ]: 4 : delete connection;
839 : 4 : }
840 : :
841 : 12 : btck_ChainParameters* btck_chain_parameters_create(const btck_ChainType chain_type)
842 : : {
843 [ + - - + : 12 : switch (chain_type) {
+ - ]
844 : 6 : case btck_ChainType_MAINNET: {
845 : 6 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::Main().release()));
846 : : }
847 : 0 : case btck_ChainType_TESTNET: {
848 : 0 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet().release()));
849 : : }
850 : 0 : case btck_ChainType_TESTNET_4: {
851 : 0 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet4().release()));
852 : : }
853 : 1 : case btck_ChainType_SIGNET: {
854 : 1 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::SigNet().release()));
855 : : }
856 : 5 : case btck_ChainType_REGTEST: {
857 : 5 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::RegTest().release()));
858 : : }
859 : : }
860 : 0 : assert(false);
861 : : }
862 : :
863 : 1 : btck_ChainParameters* btck_chain_parameters_create_signet(const void* challenge, size_t challenge_len)
864 : : {
865 [ - + ]: 1 : assert(challenge != nullptr || challenge_len == 0);
866 : 1 : const uint8_t* p = static_cast<const uint8_t*>(challenge);
867 : 1 : CChainParams::SigNetOptions options{
868 [ + - + - ]: 2 : .challenge = std::vector<uint8_t>{p, p + challenge_len},
869 [ + - ]: 1 : };
870 [ + - ]: 2 : return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::SigNet(options).release()));
871 : 1 : }
872 : :
873 : 10 : btck_ChainParameters* btck_chain_parameters_copy(const btck_ChainParameters* chain_parameters)
874 : : {
875 : 10 : return btck_ChainParameters::copy(chain_parameters);
876 : : }
877 : :
878 : 1 : const btck_ConsensusParams* btck_chain_parameters_get_consensus_params(const btck_ChainParameters* chain_parameters)
879 : : {
880 : 1 : return btck_ConsensusParams::ref(&btck_ChainParameters::get(chain_parameters).GetConsensus());
881 : : }
882 : :
883 : 27 : void btck_chain_parameters_destroy(btck_ChainParameters* chain_parameters)
884 : : {
885 [ + + ]: 27 : delete chain_parameters;
886 : 27 : }
887 : :
888 : 15 : btck_ContextOptions* btck_context_options_create()
889 : : {
890 : 15 : return btck_ContextOptions::create();
891 : : }
892 : :
893 : 9 : void btck_context_options_set_chainparams(btck_ContextOptions* options, const btck_ChainParameters* chain_parameters)
894 : : {
895 : : // Copy the chainparams, so the caller can free it again
896 : 9 : LOCK(btck_ContextOptions::get(options).m_mutex);
897 [ + - + - ]: 9 : btck_ContextOptions::get(options).m_chainparams = std::make_unique<const CChainParams>(btck_ChainParameters::get(chain_parameters));
898 : 9 : }
899 : :
900 : 9 : void btck_context_options_set_notifications(btck_ContextOptions* options, btck_NotificationInterfaceCallbacks notifications)
901 : : {
902 : : // The KernelNotifications are copy-initialized, so the caller can free them again.
903 : 9 : LOCK(btck_ContextOptions::get(options).m_mutex);
904 [ + - - + : 9 : btck_ContextOptions::get(options).m_notifications = std::make_shared<KernelNotifications>(notifications);
+ - ]
905 : 9 : }
906 : :
907 : 1 : void btck_context_options_set_validation_interface(btck_ContextOptions* options, btck_ValidationInterfaceCallbacks vi_cbs)
908 : : {
909 : 1 : LOCK(btck_ContextOptions::get(options).m_mutex);
910 [ + - - + : 1 : btck_ContextOptions::get(options).m_validation_interface = std::make_shared<KernelValidationInterface>(vi_cbs);
+ - ]
911 : 1 : }
912 : :
913 : 15 : void btck_context_options_destroy(btck_ContextOptions* options)
914 : : {
915 [ + - ]: 15 : delete options;
916 : 15 : }
917 : :
918 : 15 : btck_Context* btck_context_create(const btck_ContextOptions* options)
919 : : {
920 : 15 : bool sane{true};
921 : 15 : const ContextOptions* opts = options ? &btck_ContextOptions::get(options) : nullptr;
922 : 15 : auto context{std::make_shared<const Context>(opts, sane)};
923 [ - + ]: 15 : if (!sane) {
924 [ - - + - ]: 15 : LogError("Kernel context sanity check failed.");
925 : : return nullptr;
926 : : }
927 [ + - ]: 15 : return btck_Context::create(context);
928 : 15 : }
929 : :
930 : 5 : btck_Context* btck_context_copy(const btck_Context* context)
931 : : {
932 : 5 : return btck_Context::copy(context);
933 : : }
934 : :
935 : 1 : int btck_context_interrupt(btck_Context* context)
936 : : {
937 [ - + ]: 1 : return (*btck_Context::get(context)->m_interrupt)() ? 0 : -1;
938 : : }
939 : :
940 : 22 : void btck_context_destroy(btck_Context* context)
941 : : {
942 [ + + ]: 22 : delete context;
943 : 22 : }
944 : :
945 : 6 : const btck_BlockTreeEntry* btck_block_tree_entry_get_previous(const btck_BlockTreeEntry* entry)
946 : : {
947 [ + + ]: 6 : if (!btck_BlockTreeEntry::get(entry).pprev) {
948 : 2 : LogInfo("Genesis block has no previous.");
949 : 2 : return nullptr;
950 : : }
951 : :
952 : : return btck_BlockTreeEntry::ref(btck_BlockTreeEntry::get(entry).pprev);
953 : : }
954 : :
955 : 3 : const btck_BlockTreeEntry* btck_block_tree_entry_get_ancestor(const btck_BlockTreeEntry* block_tree_entry, int32_t height)
956 : : {
957 : 3 : const auto* ancestor{btck_BlockTreeEntry::get(block_tree_entry).GetAncestor(height)};
958 [ - + ]: 3 : assert(ancestor);
959 : 3 : return btck_BlockTreeEntry::ref(ancestor);
960 : : }
961 : :
962 : 1 : btck_BlockValidationState* btck_block_validation_state_create()
963 : : {
964 : 1 : return btck_BlockValidationState::create();
965 : : }
966 : :
967 : 0 : btck_BlockValidationState* btck_block_validation_state_copy(const btck_BlockValidationState* state)
968 : : {
969 : 0 : return btck_BlockValidationState::copy(state);
970 : : }
971 : :
972 : 209 : void btck_block_validation_state_destroy(btck_BlockValidationState* state)
973 : : {
974 [ + - ]: 209 : delete state;
975 : 209 : }
976 : :
977 : 218 : btck_ValidationMode btck_block_validation_state_get_validation_mode(const btck_BlockValidationState* block_validation_state_)
978 : : {
979 : 218 : auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_);
980 [ + + ]: 218 : if (block_validation_state.IsValid()) return btck_ValidationMode_VALID;
981 [ + - ]: 5 : if (block_validation_state.IsInvalid()) return btck_ValidationMode_INVALID;
982 : : return btck_ValidationMode_INTERNAL_ERROR;
983 : : }
984 : :
985 : 212 : btck_BlockValidationResult btck_block_validation_state_get_block_validation_result(const btck_BlockValidationState* block_validation_state_)
986 : : {
987 : 212 : auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_);
988 [ + - + + : 212 : switch (block_validation_state.GetResult()) {
- - + - -
+ ]
989 : : case BlockValidationResult::BLOCK_RESULT_UNSET:
990 : : return btck_BlockValidationResult_UNSET;
991 : 1 : case BlockValidationResult::BLOCK_CONSENSUS:
992 : 1 : return btck_BlockValidationResult_CONSENSUS;
993 : 0 : case BlockValidationResult::BLOCK_CACHED_INVALID:
994 : 0 : return btck_BlockValidationResult_CACHED_INVALID;
995 : 2 : case BlockValidationResult::BLOCK_INVALID_HEADER:
996 : 2 : return btck_BlockValidationResult_INVALID_HEADER;
997 : 1 : case BlockValidationResult::BLOCK_MUTATED:
998 : 1 : return btck_BlockValidationResult_MUTATED;
999 : 0 : case BlockValidationResult::BLOCK_MISSING_PREV:
1000 : 0 : return btck_BlockValidationResult_MISSING_PREV;
1001 : 0 : case BlockValidationResult::BLOCK_INVALID_PREV:
1002 : 0 : return btck_BlockValidationResult_INVALID_PREV;
1003 : 1 : case BlockValidationResult::BLOCK_TIME_FUTURE:
1004 : 1 : return btck_BlockValidationResult_TIME_FUTURE;
1005 : 0 : case BlockValidationResult::BLOCK_HEADER_LOW_WORK:
1006 : 0 : return btck_BlockValidationResult_HEADER_LOW_WORK;
1007 : : } // no default case, so the compiler can warn about missing cases
1008 : 0 : assert(false);
1009 : : }
1010 : :
1011 : 16 : btck_ChainstateManagerOptions* btck_chainstate_manager_options_create(const btck_Context* context, const char* data_dir, size_t data_dir_len, const char* blocks_dir, size_t blocks_dir_len)
1012 : : {
1013 [ - + ]: 16 : assert(data_dir != nullptr || data_dir_len == 0);
1014 [ - + ]: 16 : assert(blocks_dir != nullptr || blocks_dir_len == 0);
1015 [ + + ]: 16 : if (data_dir_len == 0 || blocks_dir_len == 0) {
1016 : 4 : LogError("Failed to create chainstate manager options: dir must be non-null and non-empty");
1017 : 4 : return nullptr;
1018 : : }
1019 : 12 : try {
1020 [ + - + - : 24 : fs::path abs_data_dir{fs::absolute(fs::PathFromString({data_dir, data_dir_len}))};
+ - ]
1021 [ + - ]: 12 : fs::create_directories(abs_data_dir);
1022 [ + - + - : 24 : fs::path abs_blocks_dir{fs::absolute(fs::PathFromString({blocks_dir, blocks_dir_len}))};
+ - ]
1023 [ + - ]: 12 : fs::create_directories(abs_blocks_dir);
1024 [ + - ]: 12 : return btck_ChainstateManagerOptions::create(btck_Context::get(context), abs_data_dir, abs_blocks_dir);
1025 [ - - ]: 24 : } catch (const std::exception& e) {
1026 [ - - ]: 0 : LogError("Failed to create chainstate manager options: %s", e.what());
1027 : 0 : return nullptr;
1028 : 0 : }
1029 : : }
1030 : :
1031 : 1 : void btck_chainstate_manager_options_set_worker_threads_num(btck_ChainstateManagerOptions* opts, int worker_threads)
1032 : : {
1033 : 1 : LOCK(btck_ChainstateManagerOptions::get(opts).m_mutex);
1034 [ + - ]: 1 : btck_ChainstateManagerOptions::get(opts).m_chainman_options.worker_threads_num = worker_threads;
1035 : 1 : }
1036 : :
1037 : 2 : int btck_chainstate_manager_options_set_database_cache_bytes(btck_ChainstateManagerOptions* chainman_opts, uint64_t database_cache_bytes)
1038 : : {
1039 [ + + ]: 2 : if (database_cache_bytes < MIN_DBCACHE_BYTES || database_cache_bytes > MAX_DBCACHE_BYTES) {
1040 : 1 : LogError("Failed to set database cache: size is outside the supported range.");
1041 : 1 : return -1;
1042 : : }
1043 : :
1044 : 1 : auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
1045 : 1 : LOCK(opts.m_mutex);
1046 : 1 : opts.m_db_cache_bytes = database_cache_bytes;
1047 : 1 : opts.m_blockman_options.block_tree_db_params.cache_bytes = kernel::CacheSizes{database_cache_bytes}.block_tree_db;
1048 [ + - ]: 1 : return 0;
1049 : 1 : }
1050 : :
1051 : 12 : void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* options)
1052 : : {
1053 [ + - ]: 12 : delete options;
1054 : 12 : }
1055 : :
1056 : 6 : int btck_chainstate_manager_options_set_wipe_dbs(btck_ChainstateManagerOptions* chainman_opts, int wipe_block_tree_db, int wipe_chainstate_db)
1057 : : {
1058 [ + + ]: 6 : if (wipe_block_tree_db == 1 && wipe_chainstate_db != 1) {
1059 : 1 : LogError("Wiping the block tree db without also wiping the chainstate db is currently unsupported.");
1060 : 1 : return -1;
1061 : : }
1062 : 5 : auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
1063 : 5 : LOCK(opts.m_mutex);
1064 : 5 : opts.m_blockman_options.block_tree_db_params.wipe_data = wipe_block_tree_db == 1;
1065 : 5 : opts.m_chainstate_load_options.wipe_chainstate_db = wipe_chainstate_db == 1;
1066 [ + - ]: 5 : return 0;
1067 : 5 : }
1068 : :
1069 : 3 : void btck_chainstate_manager_options_update_block_tree_db_in_memory(
1070 : : btck_ChainstateManagerOptions* chainman_opts,
1071 : : int block_tree_db_in_memory)
1072 : : {
1073 : 3 : auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
1074 : 3 : LOCK(opts.m_mutex);
1075 [ + - ]: 3 : opts.m_blockman_options.block_tree_db_params.memory_only = block_tree_db_in_memory == 1;
1076 : 3 : }
1077 : :
1078 : 3 : void btck_chainstate_manager_options_update_chainstate_db_in_memory(
1079 : : btck_ChainstateManagerOptions* chainman_opts,
1080 : : int chainstate_db_in_memory)
1081 : : {
1082 : 3 : auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
1083 : 3 : LOCK(opts.m_mutex);
1084 [ + - ]: 3 : opts.m_chainstate_load_options.coins_db_in_memory = chainstate_db_in_memory == 1;
1085 : 3 : }
1086 : :
1087 : 12 : btck_ChainstateManager* btck_chainstate_manager_create(
1088 : : const btck_ChainstateManagerOptions* chainman_opts)
1089 : : {
1090 : 12 : auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};
1091 : 12 : std::unique_ptr<ChainstateManager> chainman;
1092 : 12 : try {
1093 [ + - ]: 12 : LOCK(opts.m_mutex);
1094 [ + - + - ]: 24 : chainman = std::make_unique<ChainstateManager>(*opts.m_context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options);
1095 [ - - ]: 0 : } catch (const std::exception& e) {
1096 [ - - ]: 0 : LogError("Failed to create chainstate manager: %s", e.what());
1097 : 0 : return nullptr;
1098 : 0 : }
1099 : :
1100 : 12 : try {
1101 [ + - + - ]: 36 : const auto chainstate_load_opts{WITH_LOCK(opts.m_mutex, return opts.m_chainstate_load_options)};
1102 : :
1103 [ + - + - ]: 24 : const kernel::CacheSizes cache_sizes{WITH_LOCK(opts.m_mutex, return opts.m_db_cache_bytes)};
1104 [ + - - + ]: 12 : auto [status, chainstate_err]{node::LoadChainstate(*chainman, cache_sizes, chainstate_load_opts)};
1105 [ - + ]: 12 : if (status != node::ChainstateLoadStatus::SUCCESS) {
1106 [ # # ]: 0 : LogError("Failed to load chain state from your data directory: %s", chainstate_err.original);
1107 : : return nullptr;
1108 : : }
1109 [ + - ]: 12 : std::tie(status, chainstate_err) = node::VerifyLoadedChainstate(*chainman, chainstate_load_opts);
1110 [ - + ]: 12 : if (status != node::ChainstateLoadStatus::SUCCESS) {
1111 [ # # ]: 0 : LogError("Failed to verify loaded chain state from your datadir: %s", chainstate_err.original);
1112 : : return nullptr;
1113 : : }
1114 [ + - - + ]: 12 : if (auto result = chainman->ActivateBestChains(); !result) {
1115 [ # # # # ]: 0 : LogError("%s", util::ErrorString(result).original);
1116 : 0 : return nullptr;
1117 : 12 : }
1118 [ - - ]: 12 : } catch (const std::exception& e) {
1119 [ - - ]: 0 : LogError("Failed to load chainstate: %s", e.what());
1120 : 0 : return nullptr;
1121 : 0 : }
1122 : :
1123 [ + - ]: 12 : return btck_ChainstateManager::create(std::move(chainman), opts.m_context);
1124 : 12 : }
1125 : :
1126 : 207 : const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash)
1127 : : {
1128 [ + - + - ]: 621 : auto block_index = WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(),
1129 : : return btck_ChainstateManager::get(chainman).m_chainman->m_blockman.LookupBlockIndex(btck_BlockHash::get(block_hash)));
1130 [ - + ]: 207 : if (!block_index) {
1131 [ # # ]: 0 : LogDebug(BCLog::KERNEL, "A block with the given hash is not indexed.");
1132 : 0 : return nullptr;
1133 : : }
1134 : : return btck_BlockTreeEntry::ref(block_index);
1135 : : }
1136 : :
1137 : 206 : const btck_BlockTreeEntry* btck_chainstate_manager_get_best_entry(const btck_ChainstateManager* chainstate_manager)
1138 : : {
1139 : 206 : auto& chainman = *btck_ChainstateManager::get(chainstate_manager).m_chainman;
1140 [ + - ]: 412 : return btck_BlockTreeEntry::ref(WITH_LOCK(chainman.GetMutex(), return chainman.m_best_header));
1141 : : }
1142 : :
1143 : 12 : void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman)
1144 : : {
1145 : 12 : {
1146 : 12 : LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex());
1147 [ + + ]: 24 : for (const auto& chainstate : btck_ChainstateManager::get(chainman).m_chainman->m_chainstates) {
1148 [ + - ]: 24 : if (chainstate->CanFlushToDisk()) {
1149 [ + - ]: 12 : chainstate->ForceFlushStateToDisk();
1150 : 12 : chainstate->ResetCoinsViews();
1151 : : }
1152 : : }
1153 : 12 : }
1154 : :
1155 [ + - ]: 12 : delete chainman;
1156 : 12 : }
1157 : :
1158 : 2 : int btck_chainstate_manager_import_blocks(btck_ChainstateManager* chainman, const char** block_file_paths_data, size_t* block_file_paths_lens, size_t block_file_paths_data_len)
1159 : : {
1160 : 2 : try {
1161 : 2 : std::vector<fs::path> import_files;
1162 [ + - ]: 2 : import_files.reserve(block_file_paths_data_len);
1163 [ + + ]: 3 : for (uint32_t i = 0; i < block_file_paths_data_len; i++) {
1164 [ + - ]: 1 : if (block_file_paths_data[i] != nullptr) {
1165 [ + - + - ]: 2 : import_files.emplace_back(std::string{block_file_paths_data[i], block_file_paths_lens[i]}.c_str());
1166 : : }
1167 : : }
1168 [ - + ]: 2 : auto& chainman_ref{*btck_ChainstateManager::get(chainman).m_chainman};
1169 [ - + + - ]: 2 : node::ImportBlocks(chainman_ref, import_files);
1170 [ + - + - ]: 6 : WITH_LOCK(::cs_main, chainman_ref.UpdateIBDStatus());
1171 [ - - ]: 0 : } catch (const std::exception& e) {
1172 [ - - ]: 0 : LogError("Failed to import blocks: %s", e.what());
1173 : 0 : return -1;
1174 : 0 : }
1175 : 2 : return 0;
1176 : : }
1177 : :
1178 : 635 : btck_Block* btck_block_create(const void* raw_block, size_t raw_block_length)
1179 : : {
1180 [ - + ]: 635 : assert(raw_block != nullptr || raw_block_length == 0);
1181 : 635 : auto block{std::make_shared<CBlock>()};
1182 : :
1183 [ + + ]: 635 : SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_block), raw_block_length}};
1184 : :
1185 : 635 : try {
1186 [ + + ]: 635 : stream >> TX_WITH_WITNESS(*block);
1187 : 3 : } catch (...) {
1188 [ + - + - : 3 : LogDebug(BCLog::KERNEL, "Block decode failed.");
+ - ]
1189 : 3 : return nullptr;
1190 [ + - ]: 3 : }
1191 : :
1192 [ + - ]: 632 : return btck_Block::create(block);
1193 : 635 : }
1194 : :
1195 : 5 : btck_Block* btck_block_copy(const btck_Block* block)
1196 : : {
1197 : 5 : return btck_Block::copy(block);
1198 : : }
1199 : :
1200 : 7 : int btck_block_check(const btck_Block* block, const btck_ConsensusParams* consensus_params, btck_BlockCheckFlags flags, btck_BlockValidationState* validation_state)
1201 : : {
1202 : 7 : auto& state = btck_BlockValidationState::get(validation_state);
1203 : 7 : state = BlockValidationState{};
1204 : :
1205 : 7 : const bool check_pow = (flags & btck_BlockCheckFlags_POW) != 0;
1206 : 7 : const bool check_merkle = (flags & btck_BlockCheckFlags_MERKLE) != 0;
1207 : :
1208 : 7 : const bool result = CheckBlock(*btck_Block::get(block), state, btck_ConsensusParams::get(consensus_params), /*fCheckPOW=*/check_pow, /*fCheckMerkleRoot=*/check_merkle);
1209 : :
1210 [ + + ]: 7 : return result ? 1 : 0;
1211 : : }
1212 : :
1213 : 6688 : size_t btck_block_count_transactions(const btck_Block* block)
1214 : : {
1215 [ - + ]: 6688 : return btck_Block::get(block)->vtx.size();
1216 : : }
1217 : :
1218 : 8051 : const btck_Transaction* btck_block_get_transaction_at(const btck_Block* block, size_t index)
1219 : : {
1220 [ - + - + ]: 8051 : assert(index < btck_Block::get(block)->vtx.size());
1221 : 8051 : return btck_Transaction::ref(&btck_Block::get(block)->vtx[index]);
1222 : : }
1223 : :
1224 : 209 : btck_BlockHeader* btck_block_get_header(const btck_Block* block)
1225 : : {
1226 : 209 : const auto& block_ptr = btck_Block::get(block);
1227 : 209 : return btck_BlockHeader::create(static_cast<const CBlockHeader&>(*block_ptr));
1228 : : }
1229 : :
1230 : 22 : int btck_block_to_bytes(const btck_Block* block, btck_WriteBytes writer, void* user_data)
1231 : : {
1232 : 22 : try {
1233 : 22 : WriterStream ws{writer, user_data};
1234 [ + - ]: 44 : ws << TX_WITH_WITNESS(*btck_Block::get(block));
1235 : : return 0;
1236 : 0 : } catch (...) {
1237 : 0 : return -1;
1238 : 0 : }
1239 : : }
1240 : :
1241 : 1 : btck_BlockHash* btck_block_get_hash(const btck_Block* block)
1242 : : {
1243 : 1 : return btck_BlockHash::create(btck_Block::get(block)->GetHash());
1244 : : }
1245 : :
1246 : 7323 : void btck_block_destroy(btck_Block* block)
1247 : : {
1248 [ + + ]: 7323 : delete block;
1249 : 7323 : }
1250 : :
1251 : 6676 : btck_Block* btck_block_read(const btck_ChainstateManager* chainman, const btck_BlockTreeEntry* entry)
1252 : : {
1253 : 6676 : auto block{std::make_shared<CBlock>()};
1254 [ + - + + ]: 6676 : if (!btck_ChainstateManager::get(chainman).m_chainman->m_blockman.ReadBlock(*block, btck_BlockTreeEntry::get(entry))) {
1255 [ + - + - ]: 6676 : LogError("Failed to read block.");
1256 : : return nullptr;
1257 : : }
1258 [ + - ]: 6675 : return btck_Block::create(block);
1259 : 6676 : }
1260 : :
1261 : 206 : btck_BlockHeader* btck_block_tree_entry_get_block_header(const btck_BlockTreeEntry* entry)
1262 : : {
1263 : 206 : return btck_BlockHeader::create(btck_BlockTreeEntry::get(entry).GetBlockHeader());
1264 : : }
1265 : :
1266 : 211 : int32_t btck_block_tree_entry_get_height(const btck_BlockTreeEntry* entry)
1267 : : {
1268 : 211 : return btck_BlockTreeEntry::get(entry).nHeight;
1269 : : }
1270 : :
1271 : 207 : const btck_BlockHash* btck_block_tree_entry_get_block_hash(const btck_BlockTreeEntry* entry)
1272 : : {
1273 : 207 : return btck_BlockHash::ref(btck_BlockTreeEntry::get(entry).phashBlock);
1274 : : }
1275 : :
1276 : 10 : int btck_block_tree_entry_equals(const btck_BlockTreeEntry* entry1, const btck_BlockTreeEntry* entry2)
1277 : : {
1278 : 10 : return &btck_BlockTreeEntry::get(entry1) == &btck_BlockTreeEntry::get(entry2);
1279 : : }
1280 : :
1281 : 2 : btck_BlockHash* btck_block_hash_create(const unsigned char block_hash[32])
1282 : : {
1283 : 2 : return btck_BlockHash::create(std::span<const unsigned char>{block_hash, 32});
1284 : : }
1285 : :
1286 : 212 : btck_BlockHash* btck_block_hash_copy(const btck_BlockHash* block_hash)
1287 : : {
1288 : 212 : return btck_BlockHash::copy(block_hash);
1289 : : }
1290 : :
1291 : 18 : void btck_block_hash_to_bytes(const btck_BlockHash* block_hash, unsigned char output[32])
1292 : : {
1293 : 18 : std::memcpy(output, btck_BlockHash::get(block_hash).begin(), 32);
1294 : 18 : }
1295 : :
1296 : 208 : int btck_block_hash_equals(const btck_BlockHash* hash1, const btck_BlockHash* hash2)
1297 : : {
1298 : 208 : return btck_BlockHash::get(hash1) == btck_BlockHash::get(hash2);
1299 : : }
1300 : :
1301 : 632 : void btck_block_hash_destroy(btck_BlockHash* hash)
1302 : : {
1303 [ + + ]: 632 : delete hash;
1304 : 632 : }
1305 : :
1306 : 5 : btck_BlockSpentOutputs* btck_block_spent_outputs_read(const btck_ChainstateManager* chainman, const btck_BlockTreeEntry* entry)
1307 : : {
1308 : 5 : auto block_undo{std::make_shared<CBlockUndo>()};
1309 [ + + ]: 5 : if (btck_BlockTreeEntry::get(entry).nHeight < 1) {
1310 [ + - + - : 1 : LogDebug(BCLog::KERNEL, "The genesis block does not have any spent outputs.");
+ - ]
1311 [ + - ]: 1 : return btck_BlockSpentOutputs::create(block_undo);
1312 : : }
1313 [ + - + + ]: 4 : if (!btck_ChainstateManager::get(chainman).m_chainman->m_blockman.ReadBlockUndo(*block_undo, btck_BlockTreeEntry::get(entry))) {
1314 [ + - + - ]: 5 : LogError("Failed to read block spent outputs data.");
1315 : : return nullptr;
1316 : : }
1317 [ + - ]: 3 : return btck_BlockSpentOutputs::create(block_undo);
1318 : 5 : }
1319 : :
1320 : 5 : btck_BlockSpentOutputs* btck_block_spent_outputs_copy(const btck_BlockSpentOutputs* block_spent_outputs)
1321 : : {
1322 : 5 : return btck_BlockSpentOutputs::copy(block_spent_outputs);
1323 : : }
1324 : :
1325 : 25 : size_t btck_block_spent_outputs_count(const btck_BlockSpentOutputs* block_spent_outputs)
1326 : : {
1327 [ - + ]: 25 : return btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.size();
1328 : : }
1329 : :
1330 : 12 : const btck_TransactionSpentOutputs* btck_block_spent_outputs_get_transaction_spent_outputs_at(const btck_BlockSpentOutputs* block_spent_outputs, size_t transaction_index)
1331 : : {
1332 [ - + - + ]: 12 : assert(transaction_index < btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.size());
1333 : 12 : const auto* tx_undo{&btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.at(transaction_index)};
1334 : 12 : return btck_TransactionSpentOutputs::ref(tx_undo);
1335 : : }
1336 : :
1337 : 11 : void btck_block_spent_outputs_destroy(btck_BlockSpentOutputs* block_spent_outputs)
1338 : : {
1339 [ + + ]: 11 : delete block_spent_outputs;
1340 : 11 : }
1341 : :
1342 : 7 : btck_TransactionSpentOutputs* btck_transaction_spent_outputs_copy(const btck_TransactionSpentOutputs* transaction_spent_outputs)
1343 : : {
1344 : 7 : return btck_TransactionSpentOutputs::copy(transaction_spent_outputs);
1345 : : }
1346 : :
1347 : 22 : size_t btck_transaction_spent_outputs_count(const btck_TransactionSpentOutputs* transaction_spent_outputs)
1348 : : {
1349 [ - + ]: 22 : return btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.size();
1350 : : }
1351 : :
1352 : 9 : void btck_transaction_spent_outputs_destroy(btck_TransactionSpentOutputs* transaction_spent_outputs)
1353 : : {
1354 [ + + ]: 9 : delete transaction_spent_outputs;
1355 : 9 : }
1356 : :
1357 : 12 : const btck_Coin* btck_transaction_spent_outputs_get_coin_at(const btck_TransactionSpentOutputs* transaction_spent_outputs, size_t coin_index)
1358 : : {
1359 [ - + - + ]: 12 : assert(coin_index < btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.size());
1360 : 12 : const Coin* coin{&btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.at(coin_index)};
1361 : 12 : return btck_Coin::ref(coin);
1362 : : }
1363 : :
1364 : 7 : btck_Coin* btck_coin_copy(const btck_Coin* coin)
1365 : : {
1366 : 7 : return btck_Coin::copy(coin);
1367 : : }
1368 : :
1369 : 1 : uint32_t btck_coin_confirmation_height(const btck_Coin* coin)
1370 : : {
1371 : 1 : return btck_Coin::get(coin).nHeight;
1372 : : }
1373 : :
1374 : 1 : int btck_coin_is_coinbase(const btck_Coin* coin)
1375 : : {
1376 [ + - ]: 1 : return btck_Coin::get(coin).IsCoinBase() ? 1 : 0;
1377 : : }
1378 : :
1379 : 2 : const btck_TransactionOutput* btck_coin_get_output(const btck_Coin* coin)
1380 : : {
1381 : 2 : return btck_TransactionOutput::ref(&btck_Coin::get(coin).out);
1382 : : }
1383 : :
1384 : 9 : void btck_coin_destroy(btck_Coin* coin)
1385 : : {
1386 [ + + ]: 9 : delete coin;
1387 : 9 : }
1388 : :
1389 : 418 : int btck_chainstate_manager_process_block(
1390 : : btck_ChainstateManager* chainman,
1391 : : const btck_Block* block,
1392 : : int* _new_block)
1393 : : {
1394 : 418 : bool new_block;
1395 : 418 : auto result = btck_ChainstateManager::get(chainman).m_chainman->ProcessNewBlock(btck_Block::get(block), /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
1396 [ + - ]: 418 : if (_new_block) {
1397 [ + + ]: 420 : *_new_block = new_block ? 1 : 0;
1398 : : }
1399 [ + + ]: 418 : return result ? 0 : -1;
1400 : : }
1401 : :
1402 : 208 : btck_BlockValidationState* btck_chainstate_manager_process_block_header(
1403 : : btck_ChainstateManager* chainstate_manager,
1404 : : const btck_BlockHeader* header)
1405 : : {
1406 : 208 : try {
1407 : 208 : auto& chainman = btck_ChainstateManager::get(chainstate_manager).m_chainman;
1408 : :
1409 [ + - ]: 208 : auto state = btck_BlockValidationState::create();
1410 [ + - ]: 208 : bool result{chainman->ProcessNewBlockHeaders({&btck_BlockHeader::get(header), 1}, /*min_pow_checked=*/true, btck_BlockValidationState::get(state))};
1411 [ - + ]: 208 : assert(result == btck_BlockValidationState::get(state).IsValid());
1412 : : return state;
1413 [ - - ]: 0 : } catch (const std::exception& e) {
1414 [ - - ]: 0 : LogError("Failed to process block header: %s", e.what());
1415 : 0 : return nullptr;
1416 : 0 : }
1417 : : }
1418 : :
1419 : 269 : const btck_Chain* btck_chainstate_manager_get_active_chain(const btck_ChainstateManager* chainman)
1420 : : {
1421 [ + - + - ]: 807 : return btck_Chain::ref(&WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(), return btck_ChainstateManager::get(chainman).m_chainman->ActiveChain()));
1422 : : }
1423 : :
1424 : 292 : int32_t btck_chain_get_height(const btck_Chain* chain)
1425 : : {
1426 : 292 : LOCK(::cs_main);
1427 [ - + + - ]: 292 : return btck_Chain::get(chain).Height();
1428 : 292 : }
1429 : :
1430 : 7512 : const btck_BlockTreeEntry* btck_chain_get_by_height(const btck_Chain* chain, int32_t height)
1431 : : {
1432 : 7512 : LOCK(::cs_main);
1433 [ + - + - ]: 15024 : return btck_BlockTreeEntry::ref(btck_Chain::get(chain)[height]);
1434 : 7512 : }
1435 : :
1436 : 207 : int btck_chain_contains(const btck_Chain* chain, const btck_BlockTreeEntry* entry)
1437 : : {
1438 : 207 : LOCK(::cs_main);
1439 [ + + ]: 207 : return btck_Chain::get(chain).Contains(btck_BlockTreeEntry::get(entry)) ? 1 : 0;
1440 : 207 : }
1441 : :
1442 : 4 : btck_BlockHeader* btck_block_header_create(const void* raw_block_header, size_t raw_block_header_len)
1443 : : {
1444 [ - + ]: 4 : assert(raw_block_header != nullptr && raw_block_header_len == 80);
1445 : 4 : auto header{std::make_unique<CBlockHeader>()};
1446 [ + - ]: 4 : SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_block_header), raw_block_header_len}};
1447 : :
1448 : 4 : try {
1449 [ + - ]: 4 : stream >> *header;
1450 : 0 : } catch (...) {
1451 [ - - ]: 0 : LogError("Block header decode failed.");
1452 : 0 : return nullptr;
1453 [ - - ]: 0 : }
1454 : :
1455 : 4 : return btck_BlockHeader::ref(header.release());
1456 : 4 : }
1457 : :
1458 : 5 : btck_BlockHeader* btck_block_header_copy(const btck_BlockHeader* header)
1459 : : {
1460 : 5 : return btck_BlockHeader::copy(header);
1461 : : }
1462 : :
1463 : 415 : btck_BlockHash* btck_block_header_get_hash(const btck_BlockHeader* header)
1464 : : {
1465 : 415 : return btck_BlockHash::create(btck_BlockHeader::get(header).GetHash());
1466 : : }
1467 : :
1468 : 1 : const btck_BlockHash* btck_block_header_get_prev_hash(const btck_BlockHeader* header)
1469 : : {
1470 : 1 : return btck_BlockHash::ref(&btck_BlockHeader::get(header).hashPrevBlock);
1471 : : }
1472 : :
1473 : 4 : uint32_t btck_block_header_get_timestamp(const btck_BlockHeader* header)
1474 : : {
1475 : 4 : return btck_BlockHeader::get(header).nTime;
1476 : : }
1477 : :
1478 : 3 : uint32_t btck_block_header_get_bits(const btck_BlockHeader* header)
1479 : : {
1480 : 3 : return btck_BlockHeader::get(header).nBits;
1481 : : }
1482 : :
1483 : 3 : int32_t btck_block_header_get_version(const btck_BlockHeader* header)
1484 : : {
1485 : 3 : return btck_BlockHeader::get(header).nVersion;
1486 : : }
1487 : :
1488 : 3 : uint32_t btck_block_header_get_nonce(const btck_BlockHeader* header)
1489 : : {
1490 : 3 : return btck_BlockHeader::get(header).nNonce;
1491 : : }
1492 : :
1493 : 15 : int btck_block_header_to_bytes(const btck_BlockHeader* header, unsigned char output[80])
1494 : : {
1495 : 15 : try {
1496 [ + - ]: 30 : SpanWriter{std::as_writable_bytes(std::span{output, 80})} << btck_BlockHeader::get(header);
1497 : : return 0;
1498 : 0 : } catch (...) {
1499 : 0 : return -1;
1500 : 0 : }
1501 : : }
1502 : :
1503 : 426 : void btck_block_header_destroy(btck_BlockHeader* header)
1504 : : {
1505 [ + + ]: 426 : delete header;
1506 : 426 : }
1507 : :
1508 : 12 : btck_ValidationMode btck_tx_validation_state_get_validation_mode(const btck_TxValidationState* state_)
1509 : : {
1510 : 12 : const auto& state = btck_TxValidationState::get(state_);
1511 [ + + ]: 12 : if (state.IsValid()) return btck_ValidationMode_VALID;
1512 [ + - ]: 9 : if (state.IsInvalid()) return btck_ValidationMode_INVALID;
1513 : : return btck_ValidationMode_INTERNAL_ERROR;
1514 : : }
1515 : :
1516 : 11 : btck_TxValidationState* btck_tx_validation_state_create()
1517 : : {
1518 : 11 : return btck_TxValidationState::create();
1519 : : }
1520 : :
1521 : 12 : btck_TxValidationResult btck_tx_validation_state_get_tx_validation_result(const btck_TxValidationState* state_)
1522 : : {
1523 [ + - - - : 12 : switch (btck_TxValidationState::get(state_).GetResult()) {
- - - - -
- - - -
+ ]
1524 : : case TxValidationResult::TX_RESULT_UNSET: return btck_TxValidationResult_UNSET;
1525 : 9 : case TxValidationResult::TX_CONSENSUS: return btck_TxValidationResult_CONSENSUS;
1526 : 0 : case TxValidationResult::TX_INPUTS_NOT_STANDARD: return btck_TxValidationResult_INPUTS_NOT_STANDARD;
1527 : 0 : case TxValidationResult::TX_NOT_STANDARD: return btck_TxValidationResult_NOT_STANDARD;
1528 : 0 : case TxValidationResult::TX_MISSING_INPUTS: return btck_TxValidationResult_MISSING_INPUTS;
1529 : 0 : case TxValidationResult::TX_PREMATURE_SPEND: return btck_TxValidationResult_PREMATURE_SPEND;
1530 : 0 : case TxValidationResult::TX_WITNESS_MUTATED: return btck_TxValidationResult_WITNESS_MUTATED;
1531 : 0 : case TxValidationResult::TX_WITNESS_STRIPPED: return btck_TxValidationResult_WITNESS_STRIPPED;
1532 : 0 : case TxValidationResult::TX_CONFLICT: return btck_TxValidationResult_CONFLICT;
1533 : 0 : case TxValidationResult::TX_MEMPOOL_POLICY: return btck_TxValidationResult_MEMPOOL_POLICY;
1534 : 0 : case TxValidationResult::TX_NO_MEMPOOL: return btck_TxValidationResult_NO_MEMPOOL;
1535 : 0 : case TxValidationResult::TX_RECONSIDERABLE: return btck_TxValidationResult_RECONSIDERABLE;
1536 : 0 : case TxValidationResult::TX_UNKNOWN: return btck_TxValidationResult_UNKNOWN;
1537 : : } // no default case, so the compiler can warn about missing cases
1538 : 0 : assert(false);
1539 : : }
1540 : :
1541 : 11 : void btck_tx_validation_state_destroy(btck_TxValidationState* state)
1542 : : {
1543 [ + - ]: 11 : delete state;
1544 : 11 : }
1545 : :
1546 : 12 : int btck_transaction_check(const btck_Transaction* tx, btck_TxValidationState* validation_state)
1547 : : {
1548 : 12 : auto& state = btck_TxValidationState::get(validation_state);
1549 : 12 : state = TxValidationState{};
1550 : 12 : const bool ok = CheckTransaction(*btck_Transaction::get(tx), state);
1551 [ + + ]: 12 : return ok ? 1 : 0;
1552 : : }
1553 : :
1554 : 5 : int btck_set_mock_time(int64_t timestamp)
1555 : : {
1556 : 5 : constexpr int64_t max_time{std::numeric_limits<uint32_t>::max()};
1557 [ + + ]: 5 : if (timestamp < 0 || timestamp > max_time) {
1558 : : return -1;
1559 : : }
1560 : 3 : SetMockTime(std::chrono::seconds{timestamp});
1561 : 3 : return 0;
1562 : : }
|