Branch data Line data Source code
1 : : // Copyright (c) 2024-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 : : #ifndef BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
6 : : #define BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
7 : :
8 : : #include <kernel/bitcoinkernel.h>
9 : :
10 : : #include <array>
11 : : #include <exception>
12 : : #include <functional>
13 : : #include <memory>
14 : : #include <optional>
15 : : #include <span>
16 : : #include <stdexcept>
17 : : #include <string>
18 : : #include <string_view>
19 : : #include <type_traits>
20 : : #include <utility>
21 : : #include <vector>
22 : :
23 : : namespace btck {
24 : :
25 : : enum class LogCategory : btck_LogCategory {
26 : : ALL = btck_LogCategory_ALL,
27 : : BENCH = btck_LogCategory_BENCH,
28 : : BLOCKSTORAGE = btck_LogCategory_BLOCKSTORAGE,
29 : : COINDB = btck_LogCategory_COINDB,
30 : : LEVELDB = btck_LogCategory_LEVELDB,
31 : : MEMPOOL = btck_LogCategory_MEMPOOL,
32 : : PRUNE = btck_LogCategory_PRUNE,
33 : : RAND = btck_LogCategory_RAND,
34 : : REINDEX = btck_LogCategory_REINDEX,
35 : : VALIDATION = btck_LogCategory_VALIDATION,
36 : : KERNEL = btck_LogCategory_KERNEL
37 : : };
38 : :
39 : : enum class LogLevel : btck_LogLevel {
40 : : TRACE_LEVEL = btck_LogLevel_TRACE,
41 : : DEBUG_LEVEL = btck_LogLevel_DEBUG,
42 : : INFO_LEVEL = btck_LogLevel_INFO
43 : : };
44 : :
45 : : enum class ChainType : btck_ChainType {
46 : : MAINNET = btck_ChainType_MAINNET,
47 : : TESTNET = btck_ChainType_TESTNET,
48 : : TESTNET_4 = btck_ChainType_TESTNET_4,
49 : : SIGNET = btck_ChainType_SIGNET,
50 : : REGTEST = btck_ChainType_REGTEST
51 : : };
52 : :
53 : : enum class SynchronizationState : btck_SynchronizationState {
54 : : INIT_REINDEX = btck_SynchronizationState_INIT_REINDEX,
55 : : INIT_DOWNLOAD = btck_SynchronizationState_INIT_DOWNLOAD,
56 : : POST_INIT = btck_SynchronizationState_POST_INIT
57 : : };
58 : :
59 : : enum class Warning : btck_Warning {
60 : : UNKNOWN_NEW_RULES_ACTIVATED = btck_Warning_UNKNOWN_NEW_RULES_ACTIVATED,
61 : : LARGE_WORK_INVALID_CHAIN = btck_Warning_LARGE_WORK_INVALID_CHAIN
62 : : };
63 : :
64 : : enum class ValidationMode : btck_ValidationMode {
65 : : VALID = btck_ValidationMode_VALID,
66 : : INVALID = btck_ValidationMode_INVALID,
67 : : INTERNAL_ERROR = btck_ValidationMode_INTERNAL_ERROR
68 : : };
69 : :
70 : : enum class BlockValidationResult : btck_BlockValidationResult {
71 : : UNSET = btck_BlockValidationResult_UNSET,
72 : : CONSENSUS = btck_BlockValidationResult_CONSENSUS,
73 : : CACHED_INVALID = btck_BlockValidationResult_CACHED_INVALID,
74 : : INVALID_HEADER = btck_BlockValidationResult_INVALID_HEADER,
75 : : MUTATED = btck_BlockValidationResult_MUTATED,
76 : : MISSING_PREV = btck_BlockValidationResult_MISSING_PREV,
77 : : INVALID_PREV = btck_BlockValidationResult_INVALID_PREV,
78 : : TIME_FUTURE = btck_BlockValidationResult_TIME_FUTURE,
79 : : HEADER_LOW_WORK = btck_BlockValidationResult_HEADER_LOW_WORK
80 : : };
81 : :
82 : : enum class TxValidationResult : btck_TxValidationResult {
83 : : UNSET = btck_TxValidationResult_UNSET,
84 : : CONSENSUS = btck_TxValidationResult_CONSENSUS,
85 : : INPUTS_NOT_STANDARD = btck_TxValidationResult_INPUTS_NOT_STANDARD,
86 : : NOT_STANDARD = btck_TxValidationResult_NOT_STANDARD,
87 : : MISSING_INPUTS = btck_TxValidationResult_MISSING_INPUTS,
88 : : PREMATURE_SPEND = btck_TxValidationResult_PREMATURE_SPEND,
89 : : WITNESS_MUTATED = btck_TxValidationResult_WITNESS_MUTATED,
90 : : WITNESS_STRIPPED = btck_TxValidationResult_WITNESS_STRIPPED,
91 : : CONFLICT = btck_TxValidationResult_CONFLICT,
92 : : MEMPOOL_POLICY = btck_TxValidationResult_MEMPOOL_POLICY,
93 : : NO_MEMPOOL = btck_TxValidationResult_NO_MEMPOOL,
94 : : RECONSIDERABLE = btck_TxValidationResult_RECONSIDERABLE,
95 : : UNKNOWN = btck_TxValidationResult_UNKNOWN
96 : : };
97 : :
98 : : enum class ScriptVerifyStatus : btck_ScriptVerifyStatus {
99 : : OK = btck_ScriptVerifyStatus_OK,
100 : : ERROR_INVALID_FLAGS_COMBINATION = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION,
101 : : ERROR_SPENT_OUTPUTS_REQUIRED = btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED,
102 : : };
103 : :
104 : : enum class ScriptVerificationFlags : btck_ScriptVerificationFlags {
105 : : NONE = btck_ScriptVerificationFlags_NONE,
106 : : P2SH = btck_ScriptVerificationFlags_P2SH,
107 : : DERSIG = btck_ScriptVerificationFlags_DERSIG,
108 : : NULLDUMMY = btck_ScriptVerificationFlags_NULLDUMMY,
109 : : CHECKLOCKTIMEVERIFY = btck_ScriptVerificationFlags_CHECKLOCKTIMEVERIFY,
110 : : CHECKSEQUENCEVERIFY = btck_ScriptVerificationFlags_CHECKSEQUENCEVERIFY,
111 : : WITNESS = btck_ScriptVerificationFlags_WITNESS,
112 : : TAPROOT = btck_ScriptVerificationFlags_TAPROOT,
113 : : ALL = btck_ScriptVerificationFlags_ALL
114 : : };
115 : :
116 : : enum class BlockCheckFlags : btck_BlockCheckFlags {
117 : : BASE = btck_BlockCheckFlags_BASE,
118 : : POW = btck_BlockCheckFlags_POW,
119 : : MERKLE = btck_BlockCheckFlags_MERKLE,
120 : : ALL = btck_BlockCheckFlags_ALL
121 : : };
122 : :
123 : : template <typename T>
124 : : struct is_bitmask_enum : std::false_type {
125 : : };
126 : :
127 : : template <>
128 : : struct is_bitmask_enum<ScriptVerificationFlags> : std::true_type {
129 : : };
130 : :
131 : : template <>
132 : : struct is_bitmask_enum<BlockCheckFlags> : std::true_type {
133 : : };
134 : :
135 : : template <typename T>
136 : : concept BitmaskEnum = is_bitmask_enum<T>::value;
137 : :
138 : : template <BitmaskEnum T>
139 : : constexpr T operator|(T lhs, T rhs)
140 : : {
141 : : return static_cast<T>(
142 : : static_cast<std::underlying_type_t<T>>(lhs) | static_cast<std::underlying_type_t<T>>(rhs));
143 : : }
144 : :
145 : : template <BitmaskEnum T>
146 : : constexpr T operator&(T lhs, T rhs)
147 : : {
148 : : return static_cast<T>(
149 : : static_cast<std::underlying_type_t<T>>(lhs) & static_cast<std::underlying_type_t<T>>(rhs));
150 : : }
151 : :
152 : : template <BitmaskEnum T>
153 : : constexpr T operator^(T lhs, T rhs)
154 : : {
155 : : return static_cast<T>(
156 : : static_cast<std::underlying_type_t<T>>(lhs) ^ static_cast<std::underlying_type_t<T>>(rhs));
157 : : }
158 : :
159 : : template <BitmaskEnum T>
160 : : constexpr T operator~(T value)
161 : : {
162 : : return static_cast<T>(~static_cast<std::underlying_type_t<T>>(value));
163 : : }
164 : :
165 : : template <BitmaskEnum T>
166 : : constexpr T& operator|=(T& lhs, T rhs)
167 : : {
168 : : return lhs = lhs | rhs;
169 : : }
170 : :
171 : : template <BitmaskEnum T>
172 : : constexpr T& operator&=(T& lhs, T rhs)
173 : : {
174 : : return lhs = lhs & rhs;
175 : : }
176 : :
177 : : template <BitmaskEnum T>
178 : : constexpr T& operator^=(T& lhs, T rhs)
179 : : {
180 : : return lhs = lhs ^ rhs;
181 : : }
182 : :
183 : : template <typename T>
184 : 36026 : T check(T ptr)
185 : : {
186 [ + + ]: 36026 : if (ptr == nullptr) {
187 [ + - ]: 11 : throw std::runtime_error("failed to instantiate btck object");
188 : : }
189 : 36015 : return ptr;
190 : : }
191 : :
192 : : template <typename Collection, typename ValueType>
193 : : class Iterator
194 : : {
195 : : public:
196 : : using iterator_category = std::random_access_iterator_tag;
197 : : using iterator_concept = std::random_access_iterator_tag;
198 : : using difference_type = std::ptrdiff_t;
199 : : using value_type = ValueType;
200 : :
201 : : private:
202 : : const Collection* m_collection;
203 : : size_t m_idx;
204 : :
205 : : public:
206 : : Iterator() = default;
207 : : Iterator(const Collection* ptr) : m_collection{ptr}, m_idx{0} {}
208 : 15130 : Iterator(const Collection* ptr, size_t idx) : m_collection{ptr}, m_idx{idx} {}
209 : :
210 : : // This is just a view, so return a copy.
211 [ + - + - : 15917 : auto operator*() const { return (*m_collection)[m_idx]; }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
212 : : auto operator->() const { return (*m_collection)[m_idx]; }
213 : :
214 : 15801 : auto& operator++() { m_idx++; return *this; }
215 : 6 : auto operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
216 : :
217 : 221 : auto& operator--() { m_idx--; return *this; }
218 : 6 : auto operator--(int) { auto temp = *this; --m_idx; return temp; }
219 : :
220 : 6 : auto& operator+=(difference_type n) { m_idx += n; return *this; }
221 : 6 : auto& operator-=(difference_type n) { m_idx -= n; return *this; }
222 : :
223 [ + - + - : 6 : auto operator+(difference_type n) const { return Iterator(m_collection, m_idx + n); }
+ - + - +
- + - ]
224 : : auto operator-(difference_type n) const { return Iterator(m_collection, m_idx - n); }
225 : :
226 [ + - + - : 6 : auto operator-(const Iterator& other) const { return static_cast<difference_type>(m_idx) - static_cast<difference_type>(other.m_idx); }
+ - + - +
- + - ]
227 : :
228 : 6 : ValueType operator[](difference_type n) const { return (*m_collection)[m_idx + n]; }
229 : :
230 [ + - + - : 24 : auto operator<=>(const Iterator& other) const { return m_idx <=> other.m_idx; }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
231 : :
232 [ + - + - : 23288 : bool operator==(const Iterator& other) const { return m_collection == other.m_collection && m_idx == other.m_idx; }
+ - + - +
- - + + +
+ - + + +
- + - + -
- + + + +
- + + + -
+ - + - -
+ + + + -
+ + + - +
- + - - +
+ + + - +
+ + - + -
+ - - + +
+ + - + +
+ - + - +
- - + + +
+ - + + +
- + + + -
+ + + - +
+ + - + +
+ - + + +
- + + + -
+ + + - +
+ + - + +
+ - + + +
- + - + -
+ + + - +
+ ]
233 : :
234 : : private:
235 [ + - + - : 6 : friend Iterator operator+(difference_type n, const Iterator& it) { return it + n; }
+ - + - +
- + - ]
236 : : };
237 : :
238 : : template <typename Container, typename SizeFunc, typename GetFunc>
239 : : concept IndexedContainer = requires(const Container& c, SizeFunc size_func, GetFunc get_func, std::size_t i) {
240 : : { std::invoke(size_func, c) } -> std::convertible_to<std::size_t>;
241 : : { std::invoke(get_func, c, i) }; // Return type is deduced
242 : : };
243 : :
244 : : template <typename Container, auto SizeFunc, auto GetFunc>
245 : : requires IndexedContainer<Container, decltype(SizeFunc), decltype(GetFunc)>
246 : : class Range
247 : : {
248 : : public:
249 : : using value_type = std::invoke_result_t<decltype(GetFunc), const Container&, size_t>;
250 : : using difference_type = std::ptrdiff_t;
251 : : using iterator = Iterator<Range, value_type>;
252 : : using const_iterator = iterator;
253 : :
254 : : private:
255 : : const Container* m_container;
256 : :
257 : : public:
258 : 7268 : explicit Range(const Container& container) : m_container(&container)
259 : : {
260 : : static_assert(std::ranges::random_access_range<Range>);
261 : : }
262 : :
263 [ + - + - : 533 : iterator begin() const { return iterator(this, 0); }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
264 : 7313 : iterator end() const { return iterator(this, size()); }
265 : :
266 [ + - + - : 6 : const_iterator cbegin() const { return begin(); }
+ - + - +
- + - ]
267 [ + - + - : 6 : const_iterator cend() const { return end(); }
+ - + - +
- + - ]
268 : :
269 : 15160 : size_t size() const { return std::invoke(SizeFunc, *m_container); }
270 : :
271 [ + - + - : 7 : bool empty() const { return size() == 0; }
+ - + - +
- + - +
- ]
272 : :
273 : 32786 : value_type operator[](size_t index) const { return std::invoke(GetFunc, *m_container, index); }
274 : :
275 : 6 : value_type at(size_t index) const
276 : : {
277 [ + - ]: 6 : if (index >= size()) {
278 [ + - ]: 6 : throw std::out_of_range("Index out of range");
279 : : }
280 : 0 : return (*this)[index];
281 : : }
282 : :
283 : 7 : value_type front() const { return (*this)[0]; }
284 : 9 : value_type back() const { return (*this)[size() - 1]; }
285 : : };
286 : :
287 : : #define MAKE_RANGE_METHOD(method_name, ContainerType, SizeFunc, GetFunc, container_expr) \
288 : : auto method_name() const & { \
289 : : return Range<ContainerType, SizeFunc, GetFunc>{container_expr}; \
290 : : } \
291 : : auto method_name() const && = delete;
292 : :
293 : : template <typename T>
294 : 606 : std::vector<std::byte> write_bytes(const T* object, int (*to_bytes)(const T*, btck_WriteBytes, void*))
295 : : {
296 : 606 : std::vector<std::byte> bytes;
297 [ - - ]: 0 : struct UserData {
298 : : std::vector<std::byte>* bytes;
299 : : std::exception_ptr exception;
300 : : };
301 [ + - ]: 606 : UserData user_data = UserData{.bytes = &bytes, .exception = nullptr};
302 : :
303 : 1998 : constexpr auto const write = +[](const void* buffer, size_t len, void* user_data) -> int {
304 : 1392 : auto& data = *reinterpret_cast<UserData*>(user_data);
305 : 1392 : auto& bytes = *data.bytes;
306 : : try {
307 : 1392 : auto const* first = static_cast<const std::byte*>(buffer);
308 [ + - + - : 1392 : auto const* last = first + len;
+ - + - +
- ]
309 [ + - + - : 1392 : bytes.insert(bytes.end(), first, last);
+ - + - +
- ]
310 : : return 0;
311 : 0 : } catch (...) {
312 [ - - - - : 0 : data.exception = std::current_exception();
- - - - -
- ]
313 : : return -1;
314 : : }
315 : : };
316 : :
317 [ + - - + ]: 606 : if (to_bytes(object, write, &user_data) != 0) {
318 : 0 : std::rethrow_exception(user_data.exception);
319 : : }
320 [ - + ]: 606 : return bytes;
321 : 606 : }
322 : :
323 : : template <typename CType>
324 : : class View
325 : : {
326 : : protected:
327 : : const CType* m_ptr;
328 : :
329 : : public:
330 : 52928 : explicit View(const CType* ptr) : m_ptr{check(ptr)} {}
331 : :
332 [ + - + - : 233 : const CType* get() const { return m_ptr; }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
333 : : };
334 : :
335 : : template <typename CType, CType* (*CopyFunc)(const CType*), void (*DestroyFunc)(CType*)>
336 : : class Handle
337 : : {
338 : : protected:
339 : : CType* m_ptr;
340 : :
341 : : public:
342 : 18827 : explicit Handle(CType* ptr) : m_ptr{check(ptr)} {}
343 : :
344 : : // Copy constructors
345 : 90 : Handle(const Handle& other)
346 : 90 : : m_ptr{check(CopyFunc(other.m_ptr))} {}
347 : 18 : Handle& operator=(const Handle& other)
348 : : {
349 [ + - ]: 18 : if (this != &other) {
350 : 18 : Handle temp(other);
351 : 18 : std::swap(m_ptr, temp.m_ptr);
352 : 18 : }
353 : 18 : return *this;
354 : : }
355 : :
356 : : // Move constructors
357 : 94 : Handle(Handle&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
358 : 18 : Handle& operator=(Handle&& other) noexcept
359 : : {
360 : : if (this != &other) {
361 : 18 : DestroyFunc(m_ptr);
362 [ + - + - : 18 : m_ptr = std::exchange(other.m_ptr, nullptr);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
363 : : }
364 : : return *this;
365 : : }
366 : :
367 : : template <typename ViewType>
368 : : requires std::derived_from<ViewType, View<CType>>
369 : 720 : Handle(const ViewType& view)
370 : 720 : : Handle{CopyFunc(view.get())}
371 : : {
372 : 720 : }
373 : :
374 : 92 : ~Handle() { DestroyFunc(m_ptr); }
375 : :
376 [ + - + - : 159 : CType* get() { return m_ptr; }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
377 [ + - + - ]: 25 : const CType* get() const { return m_ptr; }
378 : : };
379 : :
380 : : template <typename CType, void (*DestroyFunc)(CType*)>
381 : 98 : class UniqueHandle
382 : : {
383 : : protected:
384 : : struct Deleter {
385 : 51 : void operator()(CType* ptr) const noexcept
386 : : {
387 : : if (ptr) DestroyFunc(ptr);
388 : 51 : }
389 : : };
390 : : std::unique_ptr<CType, Deleter> m_ptr;
391 : :
392 : : public:
393 : 106 : explicit UniqueHandle(CType* ptr) : m_ptr{check(ptr)} {}
394 : :
395 [ + - + - : 4 : CType* get() { return m_ptr.get(); }
+ - ]
396 : 7398 : const CType* get() const { return m_ptr.get(); }
397 : : };
398 : :
399 : : class PrecomputedTransactionData;
400 : : class Transaction;
401 : : class TransactionOutput;
402 : : class BlockValidationState;
403 : :
404 : : template <typename Derived>
405 : : class ScriptPubkeyApi
406 : : {
407 : : private:
408 : 632 : auto impl() const
409 : : {
410 : 635 : return static_cast<const Derived*>(this)->get();
411 : : }
412 : :
413 : : friend Derived;
414 : : ScriptPubkeyApi() = default;
415 : :
416 : : public:
417 : : bool Verify(int64_t amount,
418 : : const Transaction& tx_to,
419 : : const PrecomputedTransactionData* precomputed_txdata,
420 : : unsigned int input_index,
421 : : ScriptVerificationFlags flags,
422 : : ScriptVerifyStatus& status) const;
423 : :
424 : 555 : std::vector<std::byte> ToBytes() const
425 : : {
426 [ + - + - : 553 : return write_bytes(impl(), btck_script_pubkey_to_bytes);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
427 : : }
428 : : };
429 : :
430 : : class ScriptPubkeyView : public View<btck_ScriptPubkey>, public ScriptPubkeyApi<ScriptPubkeyView>
431 : : {
432 : : public:
433 : 1170 : explicit ScriptPubkeyView(const btck_ScriptPubkey* ptr) : View{ptr} {}
434 : : };
435 : :
436 [ + - + - : 25 : class ScriptPubkey : public Handle<btck_ScriptPubkey, btck_script_pubkey_copy, btck_script_pubkey_destroy>, public ScriptPubkeyApi<ScriptPubkey>
+ - + - +
- + - + -
+ - + - +
- ]
437 : : {
438 : : public:
439 : 11 : explicit ScriptPubkey(std::span<const std::byte> raw)
440 : 11 : : Handle{btck_script_pubkey_create(raw.data(), raw.size())} {}
441 : :
442 : 2 : ScriptPubkey(const ScriptPubkeyView& view)
443 [ + - + - ]: 2 : : Handle(view) {}
444 : : };
445 : :
446 : : template <typename Derived>
447 : : class TransactionOutputApi
448 : : {
449 : : private:
450 : 973 : auto impl() const
451 : : {
452 : 973 : return static_cast<const Derived*>(this)->get();
453 : : }
454 : :
455 : : friend Derived;
456 : : TransactionOutputApi() = default;
457 : :
458 : : public:
459 : 386 : int64_t Amount() const
460 : : {
461 [ + - + - : 386 : return btck_transaction_output_get_amount(impl());
+ - + - +
- + - + -
+ - + - +
- + - ]
462 : : }
463 : :
464 : 585 : ScriptPubkeyView GetScriptPubkey() const
465 : : {
466 : 585 : return ScriptPubkeyView{btck_transaction_output_get_script_pubkey(impl())};
467 : : }
468 : : };
469 : :
470 : : class TransactionOutputView : public View<btck_TransactionOutput>, public TransactionOutputApi<TransactionOutputView>
471 : : {
472 : : public:
473 : 1206 : explicit TransactionOutputView(const btck_TransactionOutput* ptr) : View{ptr} {}
474 : : };
475 : :
476 [ + - + - : 79 : class TransactionOutput : public Handle<btck_TransactionOutput, btck_transaction_output_copy, btck_transaction_output_destroy>, public TransactionOutputApi<TransactionOutput>
+ - + - +
- + - +
- ]
477 : : {
478 : : public:
479 : 5 : explicit TransactionOutput(const ScriptPubkey& script_pubkey, int64_t amount)
480 : 5 : : Handle{btck_transaction_output_create(script_pubkey.get(), amount)} {}
481 : :
482 : 61 : TransactionOutput(const TransactionOutputView& view)
483 [ + - + - : 61 : : Handle(view) {}
+ - ]
484 : : };
485 : :
486 : : template <typename Derived>
487 : : class TxidApi
488 : : {
489 : : private:
490 : 7644 : auto impl() const
491 : : {
492 : 7645 : return static_cast<const Derived*>(this)->get();
493 : : }
494 : :
495 : : friend Derived;
496 : : TxidApi() = default;
497 : :
498 : : public:
499 : 7572 : bool operator==(const TxidApi& other) const
500 : : {
501 [ + - + - : 7572 : return btck_txid_equals(impl(), other.impl()) != 0;
+ - + - +
- ]
502 : : }
503 : :
504 : 60 : bool operator!=(const TxidApi& other) const
505 : : {
506 [ + - + - : 60 : return btck_txid_equals(impl(), other.impl()) == 0;
+ - + - ]
507 : : }
508 : :
509 [ + - + - : 12 : std::array<std::byte, 32> ToBytes() const
+ - + - +
- + - + -
+ - + - +
- + - ]
510 : : {
511 : : std::array<std::byte, 32> hash;
512 [ + - + - : 12 : btck_txid_to_bytes(impl(), reinterpret_cast<unsigned char*>(hash.data()));
+ - + - +
- + - + -
+ - + - +
- + - ]
513 : 11 : return hash;
514 : : }
515 : : };
516 : :
517 : : class TxidView : public View<btck_Txid>, public TxidApi<TxidView>
518 : : {
519 : : public:
520 : 15620 : explicit TxidView(const btck_Txid* ptr) : View{ptr} {}
521 : : };
522 : :
523 [ + - + - : 10 : class Txid : public Handle<btck_Txid, btck_txid_copy, btck_txid_destroy>, public TxidApi<Txid>
+ - + - +
- + - + -
+ - ]
524 : : {
525 : : public:
526 : 2 : Txid(const TxidView& view)
527 [ + - + - ]: 2 : : Handle(view) {}
528 : : };
529 : :
530 : : template <typename Derived>
531 : : class OutPointApi
532 : : {
533 : : private:
534 : 502 : auto impl() const
535 : : {
536 : 502 : return static_cast<const Derived*>(this)->get();
537 : : }
538 : :
539 : : friend Derived;
540 : : OutPointApi() = default;
541 : :
542 : : public:
543 : 325 : uint32_t index() const
544 : : {
545 [ + - + - ]: 325 : return btck_transaction_out_point_get_index(impl());
546 : : }
547 : :
548 : 177 : TxidView Txid() const
549 : : {
550 : 177 : return TxidView{btck_transaction_out_point_get_txid(impl())};
551 : : }
552 : : };
553 : :
554 : : class OutPointView : public View<btck_TransactionOutPoint>, public OutPointApi<OutPointView>
555 : : {
556 : : public:
557 : 536 : explicit OutPointView(const btck_TransactionOutPoint* ptr) : View{ptr} {}
558 : : };
559 : :
560 [ + - + - : 10 : class OutPoint : public Handle<btck_TransactionOutPoint, btck_transaction_out_point_copy, btck_transaction_out_point_destroy>, public OutPointApi<OutPoint>
+ - + - +
- + - + -
+ - ]
561 : : {
562 : : public:
563 : 2 : OutPoint(const OutPointView& view)
564 [ + - + - ]: 2 : : Handle(view) {}
565 : : };
566 : :
567 : : template <typename Derived>
568 : : class WitnessStackApi
569 : : {
570 : : private:
571 : 21 : auto impl() const
572 : : {
573 : 21 : return static_cast<const Derived*>(this)->get();
574 : : }
575 : :
576 : : friend Derived;
577 : : WitnessStackApi() = default;
578 : :
579 : : public:
580 : 9 : size_t CountItems() const
581 : : {
582 [ + - + - ]: 9 : return btck_witness_stack_count_items(impl());
583 : : }
584 : :
585 : 12 : std::vector<std::byte> GetItem(size_t index) const
586 : : {
587 : : struct Item { const btck_WitnessStack* stack; size_t index; };
588 : 12 : Item item{impl(), index};
589 : : return write_bytes(&item, +[](const Item* c, btck_WriteBytes w, void* ud) {
590 : : return btck_witness_stack_get_item_at(c->stack, c->index, w, ud);
591 [ + - + - : 12 : });
+ - + - +
- ]
592 : : }
593 : :
594 [ + - + - ]: 13 : MAKE_RANGE_METHOD(Items, Derived, &WitnessStackApi<Derived>::CountItems, &WitnessStackApi<Derived>::GetItem, *static_cast<const Derived*>(this))
595 : : };
596 : :
597 : : class WitnessStackView : public View<btck_WitnessStack>, public WitnessStackApi<WitnessStackView>
598 : : {
599 : : public:
600 : 4 : explicit WitnessStackView(const btck_WitnessStack* ptr) : View{ptr} {}
601 : : };
602 : :
603 [ + - + - : 10 : class WitnessStack : public Handle<btck_WitnessStack, btck_witness_stack_copy, btck_witness_stack_destroy>, public WitnessStackApi<WitnessStack>
+ - + - +
- + - + -
+ - ]
604 : : {
605 : : public:
606 : 2 : WitnessStack(const WitnessStackView& view)
607 [ + - + - ]: 1 : : Handle(view) {}
608 : : };
609 : :
610 : : template <typename Derived>
611 : : class TransactionInputApi
612 : : {
613 : : private:
614 : 274 : auto impl() const
615 : : {
616 : 274 : return static_cast<const Derived*>(this)->get();
617 : : }
618 : :
619 : : friend Derived;
620 : : TransactionInputApi() = default;
621 : :
622 : : public:
623 : 268 : OutPointView OutPoint() const
624 : : {
625 : 268 : return OutPointView{btck_transaction_input_get_out_point(impl())};
626 : : }
627 : :
628 : 1 : uint32_t GetSequence() const
629 : : {
630 [ + - ]: 1 : return btck_transaction_input_get_sequence(impl());
631 : : }
632 : :
633 : 2 : WitnessStackView GetWitnessStack() const
634 : : {
635 : 2 : return WitnessStackView{btck_transaction_input_get_witness_stack(impl())};
636 : : }
637 : :
638 : 3 : std::vector<std::byte> GetScriptSig() const
639 : : {
640 [ + - + - : 3 : return write_bytes(impl(), btck_transaction_input_get_script_sig);
+ - ]
641 : : }
642 : : };
643 : :
644 : : class TransactionInputView : public View<btck_TransactionInput>, public TransactionInputApi<TransactionInputView>
645 : : {
646 : : public:
647 : 564 : explicit TransactionInputView(const btck_TransactionInput* ptr) : View{ptr} {}
648 : : };
649 : :
650 [ + - + - : 75 : class TransactionInput : public Handle<btck_TransactionInput, btck_transaction_input_copy, btck_transaction_input_destroy>, public TransactionInputApi<TransactionInput>
+ - + - +
- + - + -
+ - ]
651 : : {
652 : : public:
653 : 61 : TransactionInput(const TransactionInputView& view)
654 [ + - + - : 61 : : Handle(view) {}
+ - ]
655 : : };
656 : :
657 : : template <typename Derived>
658 : : class TransactionApi
659 : : {
660 : : private:
661 : 9101 : auto impl() const
662 : : {
663 : 9102 : return static_cast<const Derived*>(this)->get();
664 : : }
665 : :
666 : : public:
667 : 287 : size_t CountOutputs() const
668 : : {
669 [ + - + - : 287 : return btck_transaction_count_outputs(impl());
+ - + - +
- ]
670 : : }
671 : :
672 : 284 : size_t CountInputs() const
673 : : {
674 [ + - + - : 284 : return btck_transaction_count_inputs(impl());
+ - + - +
- ]
675 : : }
676 : :
677 : 601 : TransactionOutputView GetOutput(size_t index) const
678 : : {
679 : 601 : return TransactionOutputView{btck_transaction_get_output_at(impl(), index)};
680 : : }
681 : :
682 : 282 : TransactionInputView GetInput(size_t index) const
683 : : {
684 : 282 : return TransactionInputView{btck_transaction_get_input_at(impl(), index)};
685 : : }
686 : :
687 : 1 : uint32_t GetLocktime() const
688 : : {
689 [ + - ]: 1 : return btck_transaction_get_locktime(impl());
690 : : }
691 : :
692 : 7633 : TxidView Txid() const
693 : : {
694 : 7633 : return TxidView{btck_transaction_get_txid(impl())};
695 : : }
696 : :
697 [ + - + - : 1083 : MAKE_RANGE_METHOD(Outputs, Derived, &TransactionApi<Derived>::CountOutputs, &TransactionApi<Derived>::GetOutput, *static_cast<const Derived*>(this))
+ - + - ]
698 : :
699 [ + - + - ]: 818 : MAKE_RANGE_METHOD(Inputs, Derived, &TransactionApi<Derived>::CountInputs, &TransactionApi<Derived>::GetInput, *static_cast<const Derived*>(this))
700 : :
701 : 14 : std::vector<std::byte> ToBytes() const
702 : : {
703 [ + - + - : 13 : return write_bytes(impl(), btck_transaction_to_bytes);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
704 : : }
705 : : };
706 : :
707 : : class TransactionView : public View<btck_Transaction>, public TransactionApi<TransactionView>
708 : : {
709 : : public:
710 : 16098 : explicit TransactionView(const btck_Transaction* ptr) : View{ptr} {}
711 : : };
712 : :
713 [ + - + - : 468 : class Transaction : public Handle<btck_Transaction, btck_transaction_copy, btck_transaction_destroy>, public TransactionApi<Transaction>
+ - + - +
- + - + -
+ - - - -
- - - +
- ]
714 : : {
715 : : public:
716 : 27 : explicit Transaction(std::span<const std::byte> raw_transaction)
717 : 27 : : Handle{btck_transaction_create(raw_transaction.data(), raw_transaction.size())} {}
718 : :
719 : 379 : Transaction(const TransactionView& view)
720 [ + - + - : 379 : : Handle{view} {}
+ - + - ]
721 : : };
722 : :
723 [ + - + - : 273 : class PrecomputedTransactionData : public Handle<btck_PrecomputedTransactionData, btck_precomputed_transaction_data_copy, btck_precomputed_transaction_data_destroy>
+ - + - +
- + - +
- ]
724 : : {
725 : : public:
726 : 266 : explicit PrecomputedTransactionData(const Transaction& tx_to, std::span<const TransactionOutput> spent_outputs)
727 : 266 : : Handle{btck_precomputed_transaction_data_create(
728 : : tx_to.get(),
729 : : reinterpret_cast<const btck_TransactionOutput**>(
730 : 266 : const_cast<TransactionOutput*>(spent_outputs.data())),
731 : 266 : spent_outputs.size())} {}
732 : : };
733 : :
734 : : template <typename Derived>
735 : 80 : bool ScriptPubkeyApi<Derived>::Verify(int64_t amount,
736 : : const Transaction& tx_to,
737 : : const PrecomputedTransactionData* precomputed_txdata,
738 : : unsigned int input_index,
739 : : ScriptVerificationFlags flags,
740 : : ScriptVerifyStatus& status) const
741 : : {
742 [ + + ]: 154 : auto result = btck_script_pubkey_verify(
743 : : impl(),
744 : : amount,
745 : : tx_to.get(),
746 : 74 : precomputed_txdata ? precomputed_txdata->get() : nullptr,
747 : : input_index,
748 : : static_cast<btck_ScriptVerificationFlags>(flags),
749 : : reinterpret_cast<btck_ScriptVerifyStatus*>(&status));
750 : 80 : return result == 1;
751 : : }
752 : :
753 : : template <typename Derived>
754 : : class BlockHashApi
755 : : {
756 : : private:
757 : 224 : auto impl() const
758 : : {
759 : 226 : return static_cast<const Derived*>(this)->get();
760 : : }
761 : :
762 : : public:
763 : 207 : bool operator==(const Derived& other) const
764 : : {
765 [ + - + - : 207 : return btck_block_hash_equals(impl(), other.get()) != 0;
+ - + - ]
766 : : }
767 : :
768 : 1 : bool operator!=(const Derived& other) const
769 : : {
770 [ + - + - ]: 1 : return btck_block_hash_equals(impl(), other.get()) == 0;
771 : : }
772 : :
773 [ + - + - : 17 : std::array<std::byte, 32> ToBytes() const
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
774 : : {
775 : : std::array<std::byte, 32> hash;
776 [ + - + - : 17 : btck_block_hash_to_bytes(impl(), reinterpret_cast<unsigned char*>(hash.data()));
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
777 : 16 : return hash;
778 : : }
779 : : };
780 : :
781 : : class BlockHashView : public View<btck_BlockHash>, public BlockHashApi<BlockHashView>
782 : : {
783 : : public:
784 : 416 : explicit BlockHashView(const btck_BlockHash* ptr) : View{ptr} {}
785 : : };
786 : :
787 [ + - + - : 426 : class BlockHash : public Handle<btck_BlockHash, btck_block_hash_copy, btck_block_hash_destroy>, public BlockHashApi<BlockHash>
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
788 : : {
789 : : public:
790 : 2 : explicit BlockHash(const std::array<std::byte, 32>& hash)
791 : 2 : : Handle{btck_block_hash_create(reinterpret_cast<const unsigned char*>(hash.data()))} {}
792 : :
793 : 416 : explicit BlockHash(btck_BlockHash* hash)
794 : 832 : : Handle{hash} {}
795 : :
796 : 207 : BlockHash(const BlockHashView& view)
797 [ + - + - ]: 207 : : Handle{view} {}
798 : : };
799 : :
800 : : template <typename Derived>
801 : : class BlockHeaderApi
802 : : {
803 : : private:
804 : 443 : auto impl() const
805 : : {
806 : 443 : return static_cast<const Derived*>(this)->get();
807 : : }
808 : :
809 : : friend Derived;
810 : : BlockHeaderApi() = default;
811 : :
812 : : public:
813 : 415 : BlockHash Hash() const
814 : : {
815 : 415 : return BlockHash{btck_block_header_get_hash(impl())};
816 : : }
817 : :
818 : 1 : BlockHashView PrevHash() const
819 : : {
820 : 1 : return BlockHashView{btck_block_header_get_prev_hash(impl())};
821 : : }
822 : :
823 : 3 : uint32_t Timestamp() const
824 : : {
825 [ + - + - : 3 : return btck_block_header_get_timestamp(impl());
+ - ]
826 : : }
827 : :
828 : 3 : uint32_t Bits() const
829 : : {
830 [ + - + - : 3 : return btck_block_header_get_bits(impl());
+ - ]
831 : : }
832 : :
833 : 3 : int32_t Version() const
834 : : {
835 [ + - + - : 3 : return btck_block_header_get_version(impl());
+ - ]
836 : : }
837 : :
838 : 3 : uint32_t Nonce() const
839 : : {
840 [ + - + - : 3 : return btck_block_header_get_nonce(impl());
+ - ]
841 : : }
842 : :
843 : 15 : std::array<std::byte, 80> ToBytes() const
844 : : {
845 : : std::array<std::byte, 80> header;
846 : 15 : int res{btck_block_header_to_bytes(impl(), reinterpret_cast<unsigned char*>(header.data()))};
847 [ - + ]: 15 : if (res != 0) {
848 [ # # ]: 0 : throw std::runtime_error("Failed to serialize block header");
849 : : }
850 : 15 : return header;
851 : : }
852 : : };
853 : :
854 : : class BlockHeaderView : public View<btck_BlockHeader>, public BlockHeaderApi<BlockHeaderView>
855 : : {
856 : : public:
857 : : explicit BlockHeaderView(const btck_BlockHeader* ptr) : View{ptr} {}
858 : : };
859 : :
860 [ + - + - : 424 : class BlockHeader : public Handle<btck_BlockHeader, btck_block_header_copy, btck_block_header_destroy>, public BlockHeaderApi<BlockHeader>
+ - + - +
- + - + -
+ - ]
861 : : {
862 : : public:
863 : 4 : explicit BlockHeader(std::span<const std::byte> raw_header)
864 : 4 : : Handle{btck_block_header_create(reinterpret_cast<const unsigned char*>(raw_header.data()), raw_header.size())} {}
865 : :
866 : : BlockHeader(const BlockHeaderView& view)
867 : : : Handle{view} {}
868 : :
869 : 414 : BlockHeader(btck_BlockHeader* header)
870 : 828 : : Handle{header} {}
871 : : };
872 : :
873 : : class ConsensusParamsView : public View<btck_ConsensusParams>
874 : : {
875 : : public:
876 : 2 : explicit ConsensusParamsView(const btck_ConsensusParams* ptr) : View{ptr} {}
877 : : };
878 : :
879 [ + - + - : 7323 : class Block : public Handle<btck_Block, btck_block_copy, btck_block_destroy>
+ - + - +
- - - + -
+ - + - -
- - - ]
880 : : {
881 : : public:
882 : 634 : Block(const std::span<const std::byte> raw_block)
883 : 634 : : Handle{btck_block_create(raw_block.data(), raw_block.size())}
884 : : {
885 : 631 : }
886 : :
887 : 6675 : Block(btck_Block* block) : Handle{block} {}
888 : :
889 : 6688 : size_t CountTransactions() const
890 : : {
891 [ + - + - ]: 6688 : return btck_block_count_transactions(get());
892 : : }
893 : :
894 : 8049 : TransactionView GetTransaction(size_t index) const
895 : : {
896 : 8049 : return TransactionView{btck_block_get_transaction_at(get(), index)};
897 : : }
898 : :
899 : : bool Check(const ConsensusParamsView& consensus_params,
900 : : BlockCheckFlags flags,
901 : : BlockValidationState& state) const;
902 : :
903 [ + - + - : 21405 : MAKE_RANGE_METHOD(Transactions, Block, &Block::CountTransactions, &Block::GetTransaction, *this)
+ - + - +
- + - + -
+ - ]
904 : :
905 : 1 : BlockHash GetHash() const
906 : : {
907 : 1 : return BlockHash{btck_block_get_hash(get())};
908 : : }
909 : :
910 : 208 : BlockHeader GetHeader() const
911 : : {
912 : 208 : return BlockHeader{btck_block_get_header(get())};
913 : : }
914 : :
915 : 22 : std::vector<std::byte> ToBytes() const
916 : : {
917 [ + - + - : 21 : return write_bytes(get(), btck_block_to_bytes);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
918 : : }
919 : : };
920 : :
921 : : inline void logging_disable()
922 : : {
923 : : btck_logging_disable();
924 : : }
925 : :
926 : 1 : inline void logging_set_options(const btck_LoggingOptions& logging_options)
927 : : {
928 [ # # ]: 1 : btck_logging_set_options(logging_options);
929 : 0 : }
930 : :
931 : 2 : inline void logging_set_level_category(LogCategory category, LogLevel level)
932 : : {
933 : 2 : btck_logging_set_level_category(static_cast<btck_LogCategory>(category), static_cast<btck_LogLevel>(level));
934 : : }
935 : :
936 : 2 : inline void logging_enable_category(LogCategory category)
937 : : {
938 : 2 : btck_logging_enable_category(static_cast<btck_LogCategory>(category));
939 : : }
940 : :
941 : 2 : inline void logging_disable_category(LogCategory category)
942 : : {
943 : 2 : btck_logging_disable_category(static_cast<btck_LogCategory>(category));
944 : : }
945 : :
946 : : template <typename T>
947 : : concept Log = requires(T a, std::string_view message) {
948 : : { a.LogMessage(message) } -> std::same_as<void>;
949 : : };
950 : :
951 : : template <Log T>
952 [ + - - - : 7 : class Logger : UniqueHandle<btck_LoggingConnection, btck_logging_connection_destroy>
+ - + - +
- - - ][ #
# # # #
# ]
953 : : {
954 : : public:
955 : 4 : Logger(std::unique_ptr<T> log)
956 : : : UniqueHandle{btck_logging_connection_create(
957 : : +[](void* user_data, const char* message, size_t message_len) { static_cast<T*>(user_data)->LogMessage({message, message_len}); },
958 : 4 : log.release(),
959 : 4 : +[](void* user_data) { delete static_cast<T*>(user_data); })}
960 : : {
961 : 4 : }
962 : : };
963 : :
964 : : class BlockTreeEntry : public View<btck_BlockTreeEntry>
965 : : {
966 : : public:
967 : 8360 : BlockTreeEntry(const btck_BlockTreeEntry* entry)
968 : 640 : : View{entry}
969 : : {
970 : : }
971 : :
972 : 10 : bool operator==(const BlockTreeEntry& other) const
973 : : {
974 [ + - + - : 10 : return btck_block_tree_entry_equals(get(), other.get()) != 0;
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
975 : : }
976 : :
977 : 6 : std::optional<BlockTreeEntry> GetPrevious() const
978 : : {
979 : 6 : auto entry{btck_block_tree_entry_get_previous(get())};
980 [ + + ]: 6 : if (!entry) return std::nullopt;
981 : 4 : return entry;
982 : : }
983 : :
984 : 211 : int32_t GetHeight() const
985 : : {
986 [ + - + - : 211 : return btck_block_tree_entry_get_height(get());
+ - + - +
- ]
987 : : }
988 : :
989 : 207 : BlockHashView GetHash() const
990 : : {
991 : 207 : return BlockHashView{btck_block_tree_entry_get_block_hash(get())};
992 : : }
993 : :
994 : 206 : BlockHeader GetHeader() const
995 : : {
996 : 206 : return BlockHeader{btck_block_tree_entry_get_block_header(get())};
997 : : }
998 : :
999 : 3 : BlockTreeEntry GetAncestor(int32_t height) const
1000 : : {
1001 : 3 : return BlockTreeEntry{btck_block_tree_entry_get_ancestor(get(), height)};
1002 : : }
1003 : :
1004 : : };
1005 : :
1006 : 8 : class KernelNotifications
1007 : : {
1008 : : public:
1009 : 0 : virtual ~KernelNotifications() = default;
1010 : :
1011 : 427 : virtual void BlockTipHandler(SynchronizationState state, BlockTreeEntry entry, double verification_progress) {}
1012 : :
1013 : 0 : virtual void HeaderTipHandler(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
1014 : :
1015 : 13 : virtual void ProgressHandler(std::string_view title, int progress_percent, bool resume_possible) {}
1016 : :
1017 : 0 : virtual void WarningSetHandler(Warning warning, std::string_view message) {}
1018 : :
1019 : 427 : virtual void WarningUnsetHandler(Warning warning) {}
1020 : :
1021 : 0 : virtual void FlushErrorHandler(std::string_view error) {}
1022 : :
1023 : 0 : virtual void FatalErrorHandler(std::string_view error) {}
1024 : : };
1025 : :
1026 : : template <typename Derived>
1027 : : class BlockValidationStateApi
1028 : : {
1029 : : private:
1030 : 425 : auto impl() const
1031 : : {
1032 : 426 : return static_cast<const Derived*>(this)->get();
1033 : : }
1034 : :
1035 : : friend Derived;
1036 : : BlockValidationStateApi() = default;
1037 : :
1038 : : public:
1039 : 216 : ValidationMode GetValidationMode() const
1040 : : {
1041 [ + - + - : 216 : return static_cast<ValidationMode>(btck_block_validation_state_get_validation_mode(impl()));
+ - + - +
- + - + -
+ - ]
1042 : : }
1043 : :
1044 : 210 : BlockValidationResult GetBlockValidationResult() const
1045 : : {
1046 [ + - + - : 210 : return static_cast<BlockValidationResult>(btck_block_validation_state_get_block_validation_result(impl()));
+ - + - ]
1047 : : }
1048 : : };
1049 : :
1050 : : class BlockValidationStateView : public View<btck_BlockValidationState>, public BlockValidationStateApi<BlockValidationStateView>
1051 : : {
1052 : : public:
1053 : 3 : explicit BlockValidationStateView(const btck_BlockValidationState* ptr) : View{ptr} {}
1054 : : };
1055 : :
1056 : 207 : class BlockValidationState : public Handle<btck_BlockValidationState, btck_block_validation_state_copy, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
1057 : : {
1058 : : public:
1059 : 1 : explicit BlockValidationState() : Handle{btck_block_validation_state_create()} {}
1060 : :
1061 : : explicit BlockValidationState(const BlockValidationStateView& view) : Handle{view} {}
1062 : :
1063 : 412 : explicit BlockValidationState(btck_BlockValidationState* state) : Handle{state} {}
1064 : : };
1065 : :
1066 : 7 : inline bool Block::Check(const ConsensusParamsView& consensus_params,
1067 : : BlockCheckFlags flags,
1068 : : BlockValidationState& state) const
1069 : : {
1070 [ + - + - : 7 : return btck_block_check(get(), consensus_params.get(), static_cast<btck_BlockCheckFlags>(flags), state.get()) == 1;
+ - + - +
- + - + -
+ - + - +
- + - ]
1071 : : }
1072 : :
1073 [ + - - - : 22 : class TxValidationState : public UniqueHandle<btck_TxValidationState, btck_tx_validation_state_destroy>
+ - - - +
- - - ]
1074 : : {
1075 : : public:
1076 : : using UniqueHandle::UniqueHandle; // inherit ctor
1077 : 11 : explicit TxValidationState() : UniqueHandle{btck_tx_validation_state_create()} {}
1078 : :
1079 : 12 : ValidationMode GetValidationMode() const
1080 : : {
1081 [ + - + - : 12 : return static_cast<ValidationMode>(btck_tx_validation_state_get_validation_mode(get()));
+ - + - ]
1082 : : }
1083 : :
1084 : 12 : TxValidationResult GetTxValidationResult() const
1085 : : {
1086 [ + - + - : 12 : return static_cast<TxValidationResult>(btck_tx_validation_state_get_tx_validation_result(get()));
+ - + - ]
1087 : : }
1088 : : };
1089 : :
1090 : 10 : inline bool CheckTransaction(const Transaction& tx, TxValidationState& state)
1091 : : {
1092 [ + - + - : 10 : return btck_transaction_check(tx.get(), state.get()) == 1;
+ - ]
1093 : : }
1094 : :
1095 : 1 : class ValidationInterface
1096 : : {
1097 : : public:
1098 : 0 : virtual ~ValidationInterface() = default;
1099 : :
1100 : 0 : virtual void BlockChecked(Block block, BlockValidationStateView state) {}
1101 : :
1102 : 0 : virtual void PowValidBlock(BlockTreeEntry entry, Block block) {}
1103 : :
1104 : 0 : virtual void BlockConnected(Block block, BlockTreeEntry entry) {}
1105 : :
1106 : 0 : virtual void BlockDisconnected(Block block, BlockTreeEntry entry) {}
1107 : : };
1108 : :
1109 [ + - + - : 27 : class ChainParams : public Handle<btck_ChainParameters, btck_chain_parameters_copy, btck_chain_parameters_destroy>
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
[ # # # # ]
1110 : : {
1111 : : public:
1112 : 11 : explicit ChainParams(ChainType chain_type)
1113 : 11 : : Handle{btck_chain_parameters_create(static_cast<btck_ChainType>(chain_type))} {}
1114 : :
1115 : 1 : explicit ChainParams(std::span<const std::byte> signet_challenge)
1116 : 1 : : Handle{btck_chain_parameters_create_signet(signet_challenge.data(), signet_challenge.size())} {}
1117 : :
1118 : 1 : ConsensusParamsView GetConsensusParams() const
1119 : : {
1120 : 1 : return ConsensusParamsView{btck_chain_parameters_get_consensus_params(get())};
1121 : : }
1122 : : };
1123 : :
1124 [ + - + - : 24 : class ContextOptions : public UniqueHandle<btck_ContextOptions, btck_context_options_destroy>
- - + - -
- + - + -
- - - - -
- ][ # # #
# # # # #
# # ]
1125 : : {
1126 : : public:
1127 : 14 : ContextOptions() : UniqueHandle{btck_context_options_create()} {}
1128 : :
1129 : 8 : void SetChainParams(ChainParams& chain_params)
1130 : : {
1131 [ + - + - ]: 8 : btck_context_options_set_chainparams(get(), chain_params.get());
[ # # ]
1132 : 8 : }
1133 : :
1134 : : template <typename T>
1135 : 8 : void SetNotifications(std::shared_ptr<T> notifications)
1136 : : {
1137 : : static_assert(std::is_base_of_v<KernelNotifications, T>);
1138 [ + - ]: 8 : auto heap_notifications = std::make_unique<std::shared_ptr<T>>(std::move(notifications));
1139 : : using user_type = std::shared_ptr<T>*;
1140 : 8 : btck_context_options_set_notifications(
1141 : : get(),
1142 : : btck_NotificationInterfaceCallbacks{
1143 [ + - ]: 8 : .user_data = heap_notifications.release(),
1144 [ + - ]: 16 : .user_data_destroy = +[](void* user_data) { delete static_cast<user_type>(user_data); },
1145 : 427 : .block_tip = +[](void* user_data, btck_SynchronizationState state, const btck_BlockTreeEntry* entry, double verification_progress) { (*static_cast<user_type>(user_data))->BlockTipHandler(static_cast<SynchronizationState>(state), BlockTreeEntry{entry}, verification_progress); },
1146 : : .header_tip = +[](void* user_data, btck_SynchronizationState state, int64_t height, int64_t timestamp, int presync) { (*static_cast<user_type>(user_data))->HeaderTipHandler(static_cast<SynchronizationState>(state), height, timestamp, presync == 1); },
1147 : : .progress = +[](void* user_data, const char* title, size_t title_len, int progress_percent, int resume_possible) { (*static_cast<user_type>(user_data))->ProgressHandler({title, title_len}, progress_percent, resume_possible == 1); },
1148 : : .warning_set = +[](void* user_data, btck_Warning warning, const char* message, size_t message_len) { (*static_cast<user_type>(user_data))->WarningSetHandler(static_cast<Warning>(warning), {message, message_len}); },
1149 : : .warning_unset = +[](void* user_data, btck_Warning warning) { (*static_cast<user_type>(user_data))->WarningUnsetHandler(static_cast<Warning>(warning)); },
1150 : : .flush_error = +[](void* user_data, const char* error, size_t error_len) { (*static_cast<user_type>(user_data))->FlushErrorHandler({error, error_len}); },
1151 : : .fatal_error = +[](void* user_data, const char* error, size_t error_len) { (*static_cast<user_type>(user_data))->FatalErrorHandler({error, error_len}); },
1152 : : });
1153 : 8 : }
1154 : :
1155 : : template <typename T>
1156 : 1 : void SetValidationInterface(std::shared_ptr<T> validation_interface)
1157 : : {
1158 : : static_assert(std::is_base_of_v<ValidationInterface, T>);
1159 [ + - ]: 1 : auto heap_vi = std::make_unique<std::shared_ptr<T>>(std::move(validation_interface));
1160 : : using user_type = std::shared_ptr<T>*;
1161 : 1 : btck_context_options_set_validation_interface(
1162 : : get(),
1163 : : btck_ValidationInterfaceCallbacks{
1164 [ + - ]: 1 : .user_data = heap_vi.release(),
1165 [ + - ]: 2 : .user_data_destroy = +[](void* user_data) { delete static_cast<user_type>(user_data); },
1166 [ + - ]: 6 : .block_checked = +[](void* user_data, btck_Block* block, const btck_BlockValidationState* state) { (*static_cast<user_type>(user_data))->BlockChecked(Block{block}, BlockValidationStateView{state}); },
1167 [ # # # # ]: 0 : .pow_valid_block = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->PowValidBlock(BlockTreeEntry{entry}, Block{block}); },
1168 [ + - ]: 4 : .block_connected = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->BlockConnected(Block{block}, BlockTreeEntry{entry}); },
1169 [ # # ]: 0 : .block_disconnected = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->BlockDisconnected(Block{block}, BlockTreeEntry{entry}); },
1170 : : });
1171 : 1 : }
1172 : : };
1173 : :
1174 [ + - + - : 21 : class Context : public Handle<btck_Context, btck_context_copy, btck_context_destroy>
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
1175 : : {
1176 : : public:
1177 : 10 : Context(ContextOptions& opts)
1178 : 10 : : Handle{btck_context_create(opts.get())} {}
1179 : :
1180 : 4 : Context()
1181 [ + - + - : 8 : : Handle{btck_context_create(ContextOptions{}.get())} {}
+ - ]
1182 : :
1183 : 1 : bool interrupt()
1184 : : {
1185 [ + - + - ]: 1 : return btck_context_interrupt(get()) == 0;
1186 : : }
1187 : : };
1188 : :
1189 [ + - - - : 22 : class ChainstateManagerOptions : public UniqueHandle<btck_ChainstateManagerOptions, btck_chainstate_manager_options_destroy>
+ - + - -
- - - + -
- - - - -
- ][ # # #
# # # ]
1190 : : {
1191 : : public:
1192 : 15 : ChainstateManagerOptions(const Context& context, std::string_view data_dir, std::string_view blocks_dir)
1193 : 15 : : UniqueHandle{btck_chainstate_manager_options_create(
1194 : 15 : context.get(), data_dir.data(), data_dir.length(), blocks_dir.data(), blocks_dir.length())}
1195 : : {
1196 : 11 : }
1197 : :
1198 : 1 : void SetWorkerThreads(int worker_threads)
1199 : : {
1200 [ + - ]: 1 : btck_chainstate_manager_options_set_worker_threads_num(get(), worker_threads);
1201 : 1 : }
1202 : :
1203 : 6 : bool SetWipeDbs(bool wipe_block_tree, bool wipe_chainstate)
1204 : : {
1205 [ + - + - : 6 : return btck_chainstate_manager_options_set_wipe_dbs(get(), wipe_block_tree, wipe_chainstate) == 0;
+ - + - +
- + - + -
+ - + - ]
1206 : : }
1207 : :
1208 : 2 : void UpdateBlockTreeDbInMemory(bool block_tree_db_in_memory)
1209 : : {
1210 [ + - ]: 2 : btck_chainstate_manager_options_update_block_tree_db_in_memory(get(), block_tree_db_in_memory);
1211 : 2 : }
1212 : :
1213 : 2 : void UpdateChainstateDbInMemory(bool chainstate_db_in_memory)
1214 : : {
1215 [ + - ]: 2 : btck_chainstate_manager_options_update_chainstate_db_in_memory(get(), chainstate_db_in_memory);
1216 : 2 : }
1217 : : };
1218 : :
1219 : : class ChainView : public View<btck_Chain>
1220 : : {
1221 : : public:
1222 : 538 : explicit ChainView(const btck_Chain* ptr) : View{ptr} {}
1223 : :
1224 : 1 : int32_t Height() const
1225 : : {
1226 [ + - ]: 1 : return btck_chain_get_height(get());
1227 : : }
1228 : :
1229 : 291 : int32_t CountEntries() const
1230 : : {
1231 [ + - + - : 291 : return btck_chain_get_height(get()) + 1;
+ - + - ]
1232 : : }
1233 : :
1234 : 7512 : BlockTreeEntry GetByHeight(int32_t height) const
1235 : : {
1236 : 7512 : auto index{btck_chain_get_by_height(get(), height)};
1237 [ + + + - ]: 7512 : if (!index) throw std::runtime_error("No entry in the chain at the provided height");
1238 : 7511 : return index;
1239 : : }
1240 : :
1241 : 207 : bool Contains(BlockTreeEntry& entry) const
1242 : : {
1243 [ + - + - : 207 : return btck_chain_contains(get(), entry.get());
+ - ]
1244 : : }
1245 : :
1246 [ + - + - : 7859 : MAKE_RANGE_METHOD(Entries, ChainView, &ChainView::CountEntries, &ChainView::GetByHeight, *this)
+ - + - +
- + - + -
+ - ]
1247 : : };
1248 : :
1249 : : template <typename Derived>
1250 : : class CoinApi
1251 : : {
1252 : : private:
1253 : 4 : auto impl() const
1254 : : {
1255 : 4 : return static_cast<const Derived*>(this)->get();
1256 : : }
1257 : :
1258 : : friend Derived;
1259 : : CoinApi() = default;
1260 : :
1261 : : public:
1262 [ + - ]: 1 : uint32_t GetConfirmationHeight() const { return btck_coin_confirmation_height(impl()); }
1263 : :
1264 [ + - ]: 1 : bool IsCoinbase() const { return btck_coin_is_coinbase(impl()) == 1; }
1265 : :
1266 : 2 : TransactionOutputView GetOutput() const
1267 : : {
1268 : 2 : return TransactionOutputView{btck_coin_get_output(impl())};
1269 : : }
1270 : : };
1271 : :
1272 : : class CoinView : public View<btck_Coin>, public CoinApi<CoinView>
1273 : : {
1274 : : public:
1275 : 24 : explicit CoinView(const btck_Coin* ptr) : View{ptr} {}
1276 : : };
1277 : :
1278 [ + - + - : 10 : class Coin : public Handle<btck_Coin, btck_coin_copy, btck_coin_destroy>, public CoinApi<Coin>
+ - + - +
- + - + -
+ - ]
1279 : : {
1280 : : public:
1281 : : Coin(btck_Coin* coin) : Handle{coin} {}
1282 : :
1283 [ + - + - ]: 2 : Coin(const CoinView& view) : Handle{view} {}
1284 : : };
1285 : :
1286 : : template <typename Derived>
1287 : : class TransactionSpentOutputsApi
1288 : : {
1289 : : private:
1290 : 34 : auto impl() const
1291 : : {
1292 : 34 : return static_cast<const Derived*>(this)->get();
1293 : : }
1294 : :
1295 : : friend Derived;
1296 : : TransactionSpentOutputsApi() = default;
1297 : :
1298 : : public:
1299 : 22 : size_t Count() const
1300 : : {
1301 [ + - + - : 22 : return btck_transaction_spent_outputs_count(impl());
+ - ]
1302 : : }
1303 : :
1304 : 12 : CoinView GetCoin(size_t index) const
1305 : : {
1306 : 12 : return CoinView{btck_transaction_spent_outputs_get_coin_at(impl(), index)};
1307 : : }
1308 : :
1309 [ + - + - ]: 31 : MAKE_RANGE_METHOD(Coins, Derived, &TransactionSpentOutputsApi<Derived>::Count, &TransactionSpentOutputsApi<Derived>::GetCoin, *static_cast<const Derived*>(this))
1310 : : };
1311 : :
1312 : : class TransactionSpentOutputsView : public View<btck_TransactionSpentOutputs>, public TransactionSpentOutputsApi<TransactionSpentOutputsView>
1313 : : {
1314 : : public:
1315 : 24 : explicit TransactionSpentOutputsView(const btck_TransactionSpentOutputs* ptr) : View{ptr} {}
1316 : : };
1317 : :
1318 [ + - + - : 10 : class TransactionSpentOutputs : public Handle<btck_TransactionSpentOutputs, btck_transaction_spent_outputs_copy, btck_transaction_spent_outputs_destroy>,
+ - + - +
- + - + -
+ - ]
1319 : : public TransactionSpentOutputsApi<TransactionSpentOutputs>
1320 : : {
1321 : : public:
1322 : : TransactionSpentOutputs(btck_TransactionSpentOutputs* transaction_spent_outputs) : Handle{transaction_spent_outputs} {}
1323 : :
1324 [ + - + - ]: 2 : TransactionSpentOutputs(const TransactionSpentOutputsView& view) : Handle{view} {}
1325 : : };
1326 : :
1327 [ + - + - : 12 : class BlockSpentOutputs : public Handle<btck_BlockSpentOutputs, btck_block_spent_outputs_copy, btck_block_spent_outputs_destroy>
+ - + - +
- + - + -
+ - - - +
- + - ]
1328 : : {
1329 : : public:
1330 : 5 : BlockSpentOutputs(btck_BlockSpentOutputs* block_spent_outputs)
1331 : 9 : : Handle{block_spent_outputs}
1332 : : {
1333 : : }
1334 : :
1335 : 25 : size_t Count() const
1336 : : {
1337 [ + - + - : 25 : return btck_block_spent_outputs_count(get());
+ - + - +
- + - ]
1338 : : }
1339 : :
1340 : 12 : TransactionSpentOutputsView GetTxSpentOutputs(size_t tx_undo_index) const
1341 : : {
1342 : 12 : return TransactionSpentOutputsView{btck_block_spent_outputs_get_transaction_spent_outputs_at(get(), tx_undo_index)};
1343 : : }
1344 : :
1345 [ + - + - ]: 31 : MAKE_RANGE_METHOD(TxsSpentOutputs, BlockSpentOutputs, &BlockSpentOutputs::Count, &BlockSpentOutputs::GetTxSpentOutputs, *this)
1346 : : };
1347 : :
1348 [ + - + - : 22 : class ChainMan : UniqueHandle<btck_ChainstateManager, btck_chainstate_manager_destroy>
+ - + - +
- + - +
- ][ # # ]
1349 : : {
1350 : : public:
1351 : 11 : ChainMan(const Context& context, const ChainstateManagerOptions& chainman_opts)
1352 : 11 : : UniqueHandle{btck_chainstate_manager_create(chainman_opts.get())}
1353 : : {
1354 : 11 : }
1355 : :
1356 : 2 : bool ImportBlocks(const std::span<const std::string> paths)
1357 : : {
1358 : 2 : std::vector<const char*> c_paths;
1359 : 2 : std::vector<size_t> c_paths_lens;
1360 [ + - ]: 2 : c_paths.reserve(paths.size());
1361 [ + - ]: 2 : c_paths_lens.reserve(paths.size());
1362 [ + + ]: 3 : for (const auto& path : paths) {
1363 [ + - ]: 1 : c_paths.push_back(path.c_str());
1364 [ - + + - ]: 1 : c_paths_lens.push_back(path.length());
1365 : : }
1366 : :
1367 [ - + + - ]: 2 : return btck_chainstate_manager_import_blocks(get(), c_paths.data(), c_paths_lens.data(), c_paths.size()) == 0;
1368 : 2 : }
1369 : :
1370 : 418 : bool ProcessBlock(const Block& block, bool* new_block)
1371 : : {
1372 : 418 : int _new_block;
1373 : 418 : int res = btck_chainstate_manager_process_block(get(), block.get(), &_new_block);
1374 [ + - ]: 418 : if (new_block) *new_block = _new_block == 1;
1375 : 418 : return res == 0;
1376 : : }
1377 : :
1378 : 206 : BlockValidationState ProcessBlockHeader(const BlockHeader& header)
1379 : : {
1380 : 206 : auto state = btck_chainstate_manager_process_block_header(get(), header.get());
1381 : 206 : return BlockValidationState{state};
1382 : : }
1383 : :
1384 : 269 : ChainView GetChain() const
1385 : : {
1386 : 269 : return ChainView{btck_chainstate_manager_get_active_chain(get())};
1387 : : }
1388 : :
1389 : 207 : std::optional<BlockTreeEntry> GetBlockTreeEntry(const BlockHash& block_hash) const
1390 : : {
1391 : 207 : auto entry{btck_chainstate_manager_get_block_tree_entry_by_hash(get(), block_hash.get())};
1392 [ - + ]: 207 : if (!entry) return std::nullopt;
1393 : 207 : return entry;
1394 : : }
1395 : :
1396 : 206 : BlockTreeEntry GetBestEntry() const
1397 : : {
1398 : 206 : return btck_chainstate_manager_get_best_entry(get());
1399 : : }
1400 : :
1401 : 6676 : std::optional<Block> ReadBlock(const BlockTreeEntry& entry) const
1402 : : {
1403 : 6676 : auto block{btck_block_read(get(), entry.get())};
1404 [ + + ]: 6676 : if (!block) return std::nullopt;
1405 : 6675 : return block;
1406 : : }
1407 : :
1408 : 5 : BlockSpentOutputs ReadBlockSpentOutputs(const BlockTreeEntry& entry) const
1409 : : {
1410 : 5 : return btck_block_spent_outputs_read(get(), entry.get());
1411 : : }
1412 : : };
1413 : :
1414 : : } // namespace btck
1415 : :
1416 : : #endif // BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
|