bitcoinkernel_wrapper.h raw
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 T check(T ptr)
185 {
186 if (ptr == nullptr) {
187 throw std::runtime_error("failed to instantiate btck object");
188 }
189 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 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 auto operator*() const { return (*m_collection)[m_idx]; }
212 auto operator->() const { return (*m_collection)[m_idx]; }
213
214 auto& operator++() { m_idx++; return *this; }
215 auto operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
216
217 auto& operator--() { m_idx--; return *this; }
218 auto operator--(int) { auto temp = *this; --m_idx; return temp; }
219
220 auto& operator+=(difference_type n) { m_idx += n; return *this; }
221 auto& operator-=(difference_type n) { m_idx -= n; return *this; }
222
223 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 auto operator-(const Iterator& other) const { return static_cast<difference_type>(m_idx) - static_cast<difference_type>(other.m_idx); }
227
228 ValueType operator[](difference_type n) const { return (*m_collection)[m_idx + n]; }
229
230 auto operator<=>(const Iterator& other) const { return m_idx <=> other.m_idx; }
231
232 bool operator==(const Iterator& other) const { return m_collection == other.m_collection && m_idx == other.m_idx; }
233
234 private:
235 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 explicit Range(const Container& container) : m_container(&container)
259 {
260 static_assert(std::ranges::random_access_range<Range>);
261 }
262
263 iterator begin() const { return iterator(this, 0); }
264 iterator end() const { return iterator(this, size()); }
265
266 const_iterator cbegin() const { return begin(); }
267 const_iterator cend() const { return end(); }
268
269 size_t size() const { return std::invoke(SizeFunc, *m_container); }
270
271 bool empty() const { return size() == 0; }
272
273 value_type operator[](size_t index) const { return std::invoke(GetFunc, *m_container, index); }
274
275 value_type at(size_t index) const
276 {
277 if (index >= size()) {
278 throw std::out_of_range("Index out of range");
279 }
280 return (*this)[index];
281 }
282
283 value_type front() const { return (*this)[0]; }
284 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 std::vector<std::byte> write_bytes(const T* object, int (*to_bytes)(const T*, btck_WriteBytes, void*))
295 {
296 std::vector<std::byte> bytes;
297 struct UserData {
298 std::vector<std::byte>* bytes;
299 std::exception_ptr exception;
300 };
301 UserData user_data = UserData{.bytes = &bytes, .exception = nullptr};
302
303 constexpr auto const write = +[](const void* buffer, size_t len, void* user_data) -> int {
304 auto& data = *reinterpret_cast<UserData*>(user_data);
305 auto& bytes = *data.bytes;
306 try {
307 auto const* first = static_cast<const std::byte*>(buffer);
308 auto const* last = first + len;
309 bytes.insert(bytes.end(), first, last);
310 return 0;
311 } catch (...) {
312 data.exception = std::current_exception();
313 return -1;
314 }
315 };
316
317 if (to_bytes(object, write, &user_data) != 0) {
318 std::rethrow_exception(user_data.exception);
319 }
320 return bytes;
321 }
322
323 template <typename CType>
324 class View
325 {
326 protected:
327 const CType* m_ptr;
328
329 public:
330 explicit View(const CType* ptr) : m_ptr{check(ptr)} {}
331
332 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 explicit Handle(CType* ptr) : m_ptr{check(ptr)} {}
343
344 // Copy constructors
345 Handle(const Handle& other)
346 : m_ptr{check(CopyFunc(other.m_ptr))} {}
347 Handle& operator=(const Handle& other)
348 {
349 if (this != &other) {
350 Handle temp(other);
351 std::swap(m_ptr, temp.m_ptr);
352 }
353 return *this;
354 }
355
356 // Move constructors
357 Handle(Handle&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }
358 Handle& operator=(Handle&& other) noexcept
359 {
360 if (this != &other) {
361 DestroyFunc(m_ptr);
362 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 Handle(const ViewType& view)
370 : Handle{CopyFunc(view.get())}
371 {
372 }
373
374 ~Handle() { DestroyFunc(m_ptr); }
375
376 CType* get() { return m_ptr; }
377 const CType* get() const { return m_ptr; }
378 };
379
380 template <typename CType, void (*DestroyFunc)(CType*)>
381 class UniqueHandle
382 {
383 protected:
384 struct Deleter {
385 void operator()(CType* ptr) const noexcept
386 {
387 if (ptr) DestroyFunc(ptr);
388 }
389 };
390 std::unique_ptr<CType, Deleter> m_ptr;
391
392 public:
393 explicit UniqueHandle(CType* ptr) : m_ptr{check(ptr)} {}
394
395 CType* get() { return m_ptr.get(); }
396 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 auto impl() const
409 {
410 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 std::vector<std::byte> ToBytes() const
425 {
426 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 explicit ScriptPubkeyView(const btck_ScriptPubkey* ptr) : View{ptr} {}
434 };
435
436 class ScriptPubkey : public Handle<btck_ScriptPubkey, btck_script_pubkey_copy, btck_script_pubkey_destroy>, public ScriptPubkeyApi<ScriptPubkey>
437 {
438 public:
439 explicit ScriptPubkey(std::span<const std::byte> raw)
440 : Handle{btck_script_pubkey_create(raw.data(), raw.size())} {}
441
442 ScriptPubkey(const ScriptPubkeyView& view)
443 : Handle(view) {}
444 };
445
446 template <typename Derived>
447 class TransactionOutputApi
448 {
449 private:
450 auto impl() const
451 {
452 return static_cast<const Derived*>(this)->get();
453 }
454
455 friend Derived;
456 TransactionOutputApi() = default;
457
458 public:
459 int64_t Amount() const
460 {
461 return btck_transaction_output_get_amount(impl());
462 }
463
464 ScriptPubkeyView GetScriptPubkey() const
465 {
466 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 explicit TransactionOutputView(const btck_TransactionOutput* ptr) : View{ptr} {}
474 };
475
476 class TransactionOutput : public Handle<btck_TransactionOutput, btck_transaction_output_copy, btck_transaction_output_destroy>, public TransactionOutputApi<TransactionOutput>
477 {
478 public:
479 explicit TransactionOutput(const ScriptPubkey& script_pubkey, int64_t amount)
480 : Handle{btck_transaction_output_create(script_pubkey.get(), amount)} {}
481
482 TransactionOutput(const TransactionOutputView& view)
483 : Handle(view) {}
484 };
485
486 template <typename Derived>
487 class TxidApi
488 {
489 private:
490 auto impl() const
491 {
492 return static_cast<const Derived*>(this)->get();
493 }
494
495 friend Derived;
496 TxidApi() = default;
497
498 public:
499 bool operator==(const TxidApi& other) const
500 {
501 return btck_txid_equals(impl(), other.impl()) != 0;
502 }
503
504 bool operator!=(const TxidApi& other) const
505 {
506 return btck_txid_equals(impl(), other.impl()) == 0;
507 }
508
509 std::array<std::byte, 32> ToBytes() const
510 {
511 std::array<std::byte, 32> hash;
512 btck_txid_to_bytes(impl(), reinterpret_cast<unsigned char*>(hash.data()));
513 return hash;
514 }
515 };
516
517 class TxidView : public View<btck_Txid>, public TxidApi<TxidView>
518 {
519 public:
520 explicit TxidView(const btck_Txid* ptr) : View{ptr} {}
521 };
522
523 class Txid : public Handle<btck_Txid, btck_txid_copy, btck_txid_destroy>, public TxidApi<Txid>
524 {
525 public:
526 Txid(const TxidView& view)
527 : Handle(view) {}
528 };
529
530 template <typename Derived>
531 class OutPointApi
532 {
533 private:
534 auto impl() const
535 {
536 return static_cast<const Derived*>(this)->get();
537 }
538
539 friend Derived;
540 OutPointApi() = default;
541
542 public:
543 uint32_t index() const
544 {
545 return btck_transaction_out_point_get_index(impl());
546 }
547
548 TxidView Txid() const
549 {
550 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 explicit OutPointView(const btck_TransactionOutPoint* ptr) : View{ptr} {}
558 };
559
560 class OutPoint : public Handle<btck_TransactionOutPoint, btck_transaction_out_point_copy, btck_transaction_out_point_destroy>, public OutPointApi<OutPoint>
561 {
562 public:
563 OutPoint(const OutPointView& view)
564 : Handle(view) {}
565 };
566
567 template <typename Derived>
568 class WitnessStackApi
569 {
570 private:
571 auto impl() const
572 {
573 return static_cast<const Derived*>(this)->get();
574 }
575
576 friend Derived;
577 WitnessStackApi() = default;
578
579 public:
580 size_t CountItems() const
581 {
582 return btck_witness_stack_count_items(impl());
583 }
584
585 std::vector<std::byte> GetItem(size_t index) const
586 {
587 struct Item { const btck_WitnessStack* stack; size_t index; };
588 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 });
592 }
593
594 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 explicit WitnessStackView(const btck_WitnessStack* ptr) : View{ptr} {}
601 };
602
603 class WitnessStack : public Handle<btck_WitnessStack, btck_witness_stack_copy, btck_witness_stack_destroy>, public WitnessStackApi<WitnessStack>
604 {
605 public:
606 WitnessStack(const WitnessStackView& view)
607 : Handle(view) {}
608 };
609
610 template <typename Derived>
611 class TransactionInputApi
612 {
613 private:
614 auto impl() const
615 {
616 return static_cast<const Derived*>(this)->get();
617 }
618
619 friend Derived;
620 TransactionInputApi() = default;
621
622 public:
623 OutPointView OutPoint() const
624 {
625 return OutPointView{btck_transaction_input_get_out_point(impl())};
626 }
627
628 uint32_t GetSequence() const
629 {
630 return btck_transaction_input_get_sequence(impl());
631 }
632
633 WitnessStackView GetWitnessStack() const
634 {
635 return WitnessStackView{btck_transaction_input_get_witness_stack(impl())};
636 }
637
638 std::vector<std::byte> GetScriptSig() const
639 {
640 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 explicit TransactionInputView(const btck_TransactionInput* ptr) : View{ptr} {}
648 };
649
650 class TransactionInput : public Handle<btck_TransactionInput, btck_transaction_input_copy, btck_transaction_input_destroy>, public TransactionInputApi<TransactionInput>
651 {
652 public:
653 TransactionInput(const TransactionInputView& view)
654 : Handle(view) {}
655 };
656
657 template <typename Derived>
658 class TransactionApi
659 {
660 private:
661 auto impl() const
662 {
663 return static_cast<const Derived*>(this)->get();
664 }
665
666 public:
667 size_t CountOutputs() const
668 {
669 return btck_transaction_count_outputs(impl());
670 }
671
672 size_t CountInputs() const
673 {
674 return btck_transaction_count_inputs(impl());
675 }
676
677 TransactionOutputView GetOutput(size_t index) const
678 {
679 return TransactionOutputView{btck_transaction_get_output_at(impl(), index)};
680 }
681
682 TransactionInputView GetInput(size_t index) const
683 {
684 return TransactionInputView{btck_transaction_get_input_at(impl(), index)};
685 }
686
687 uint32_t GetLocktime() const
688 {
689 return btck_transaction_get_locktime(impl());
690 }
691
692 TxidView Txid() const
693 {
694 return TxidView{btck_transaction_get_txid(impl())};
695 }
696
697 MAKE_RANGE_METHOD(Outputs, Derived, &TransactionApi<Derived>::CountOutputs, &TransactionApi<Derived>::GetOutput, *static_cast<const Derived*>(this))
698
699 MAKE_RANGE_METHOD(Inputs, Derived, &TransactionApi<Derived>::CountInputs, &TransactionApi<Derived>::GetInput, *static_cast<const Derived*>(this))
700
701 std::vector<std::byte> ToBytes() const
702 {
703 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 explicit TransactionView(const btck_Transaction* ptr) : View{ptr} {}
711 };
712
713 class Transaction : public Handle<btck_Transaction, btck_transaction_copy, btck_transaction_destroy>, public TransactionApi<Transaction>
714 {
715 public:
716 explicit Transaction(std::span<const std::byte> raw_transaction)
717 : Handle{btck_transaction_create(raw_transaction.data(), raw_transaction.size())} {}
718
719 Transaction(const TransactionView& view)
720 : Handle{view} {}
721 };
722
723 class PrecomputedTransactionData : public Handle<btck_PrecomputedTransactionData, btck_precomputed_transaction_data_copy, btck_precomputed_transaction_data_destroy>
724 {
725 public:
726 explicit PrecomputedTransactionData(const Transaction& tx_to, std::span<const TransactionOutput> spent_outputs)
727 : Handle{btck_precomputed_transaction_data_create(
728 tx_to.get(),
729 reinterpret_cast<const btck_TransactionOutput**>(
730 const_cast<TransactionOutput*>(spent_outputs.data())),
731 spent_outputs.size())} {}
732 };
733
734 template <typename Derived>
735 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 auto result = btck_script_pubkey_verify(
743 impl(),
744 amount,
745 tx_to.get(),
746 precomputed_txdata ? precomputed_txdata->get() : nullptr,
747 input_index,
748 static_cast<btck_ScriptVerificationFlags>(flags),
749 reinterpret_cast<btck_ScriptVerifyStatus*>(&status));
750 return result == 1;
751 }
752
753 template <typename Derived>
754 class BlockHashApi
755 {
756 private:
757 auto impl() const
758 {
759 return static_cast<const Derived*>(this)->get();
760 }
761
762 public:
763 bool operator==(const Derived& other) const
764 {
765 return btck_block_hash_equals(impl(), other.get()) != 0;
766 }
767
768 bool operator!=(const Derived& other) const
769 {
770 return btck_block_hash_equals(impl(), other.get()) == 0;
771 }
772
773 std::array<std::byte, 32> ToBytes() const
774 {
775 std::array<std::byte, 32> hash;
776 btck_block_hash_to_bytes(impl(), reinterpret_cast<unsigned char*>(hash.data()));
777 return hash;
778 }
779 };
780
781 class BlockHashView : public View<btck_BlockHash>, public BlockHashApi<BlockHashView>
782 {
783 public:
784 explicit BlockHashView(const btck_BlockHash* ptr) : View{ptr} {}
785 };
786
787 class BlockHash : public Handle<btck_BlockHash, btck_block_hash_copy, btck_block_hash_destroy>, public BlockHashApi<BlockHash>
788 {
789 public:
790 explicit BlockHash(const std::array<std::byte, 32>& hash)
791 : Handle{btck_block_hash_create(reinterpret_cast<const unsigned char*>(hash.data()))} {}
792
793 explicit BlockHash(btck_BlockHash* hash)
794 : Handle{hash} {}
795
796 BlockHash(const BlockHashView& view)
797 : Handle{view} {}
798 };
799
800 template <typename Derived>
801 class BlockHeaderApi
802 {
803 private:
804 auto impl() const
805 {
806 return static_cast<const Derived*>(this)->get();
807 }
808
809 friend Derived;
810 BlockHeaderApi() = default;
811
812 public:
813 BlockHash Hash() const
814 {
815 return BlockHash{btck_block_header_get_hash(impl())};
816 }
817
818 BlockHashView PrevHash() const
819 {
820 return BlockHashView{btck_block_header_get_prev_hash(impl())};
821 }
822
823 uint32_t Timestamp() const
824 {
825 return btck_block_header_get_timestamp(impl());
826 }
827
828 uint32_t Bits() const
829 {
830 return btck_block_header_get_bits(impl());
831 }
832
833 int32_t Version() const
834 {
835 return btck_block_header_get_version(impl());
836 }
837
838 uint32_t Nonce() const
839 {
840 return btck_block_header_get_nonce(impl());
841 }
842
843 std::array<std::byte, 80> ToBytes() const
844 {
845 std::array<std::byte, 80> header;
846 int res{btck_block_header_to_bytes(impl(), reinterpret_cast<unsigned char*>(header.data()))};
847 if (res != 0) {
848 throw std::runtime_error("Failed to serialize block header");
849 }
850 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 class BlockHeader : public Handle<btck_BlockHeader, btck_block_header_copy, btck_block_header_destroy>, public BlockHeaderApi<BlockHeader>
861 {
862 public:
863 explicit BlockHeader(std::span<const std::byte> raw_header)
864 : 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 BlockHeader(btck_BlockHeader* header)
870 : Handle{header} {}
871 };
872
873 class ConsensusParamsView : public View<btck_ConsensusParams>
874 {
875 public:
876 explicit ConsensusParamsView(const btck_ConsensusParams* ptr) : View{ptr} {}
877 };
878
879 class Block : public Handle<btck_Block, btck_block_copy, btck_block_destroy>
880 {
881 public:
882 Block(const std::span<const std::byte> raw_block)
883 : Handle{btck_block_create(raw_block.data(), raw_block.size())}
884 {
885 }
886
887 Block(btck_Block* block) : Handle{block} {}
888
889 size_t CountTransactions() const
890 {
891 return btck_block_count_transactions(get());
892 }
893
894 TransactionView GetTransaction(size_t index) const
895 {
896 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 MAKE_RANGE_METHOD(Transactions, Block, &Block::CountTransactions, &Block::GetTransaction, *this)
904
905 BlockHash GetHash() const
906 {
907 return BlockHash{btck_block_get_hash(get())};
908 }
909
910 BlockHeader GetHeader() const
911 {
912 return BlockHeader{btck_block_get_header(get())};
913 }
914
915 std::vector<std::byte> ToBytes() const
916 {
917 return write_bytes(get(), btck_block_to_bytes);
918 }
919 };
920
921 inline void logging_disable()
922 {
923 btck_logging_disable();
924 }
925
926 inline void logging_set_options(const btck_LoggingOptions& logging_options)
927 {
928 btck_logging_set_options(logging_options);
929 }
930
931 inline void logging_set_level_category(LogCategory category, LogLevel level)
932 {
933 btck_logging_set_level_category(static_cast<btck_LogCategory>(category), static_cast<btck_LogLevel>(level));
934 }
935
936 inline void logging_enable_category(LogCategory category)
937 {
938 btck_logging_enable_category(static_cast<btck_LogCategory>(category));
939 }
940
941 inline void logging_disable_category(LogCategory category)
942 {
943 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 class Logger : UniqueHandle<btck_LoggingConnection, btck_logging_connection_destroy>
953 {
954 public:
955 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 log.release(),
959 +[](void* user_data) { delete static_cast<T*>(user_data); })}
960 {
961 }
962 };
963
964 class BlockTreeEntry : public View<btck_BlockTreeEntry>
965 {
966 public:
967 BlockTreeEntry(const btck_BlockTreeEntry* entry)
968 : View{entry}
969 {
970 }
971
972 bool operator==(const BlockTreeEntry& other) const
973 {
974 return btck_block_tree_entry_equals(get(), other.get()) != 0;
975 }
976
977 std::optional<BlockTreeEntry> GetPrevious() const
978 {
979 auto entry{btck_block_tree_entry_get_previous(get())};
980 if (!entry) return std::nullopt;
981 return entry;
982 }
983
984 int32_t GetHeight() const
985 {
986 return btck_block_tree_entry_get_height(get());
987 }
988
989 BlockHashView GetHash() const
990 {
991 return BlockHashView{btck_block_tree_entry_get_block_hash(get())};
992 }
993
994 BlockHeader GetHeader() const
995 {
996 return BlockHeader{btck_block_tree_entry_get_block_header(get())};
997 }
998
999 BlockTreeEntry GetAncestor(int32_t height) const
1000 {
1001 return BlockTreeEntry{btck_block_tree_entry_get_ancestor(get(), height)};
1002 }
1003
1004 };
1005
1006 class KernelNotifications
1007 {
1008 public:
1009 virtual ~KernelNotifications() = default;
1010
1011 virtual void BlockTipHandler(SynchronizationState state, BlockTreeEntry entry, double verification_progress) {}
1012
1013 virtual void HeaderTipHandler(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
1014
1015 virtual void ProgressHandler(std::string_view title, int progress_percent, bool resume_possible) {}
1016
1017 virtual void WarningSetHandler(Warning warning, std::string_view message) {}
1018
1019 virtual void WarningUnsetHandler(Warning warning) {}
1020
1021 virtual void FlushErrorHandler(std::string_view error) {}
1022
1023 virtual void FatalErrorHandler(std::string_view error) {}
1024 };
1025
1026 template <typename Derived>
1027 class BlockValidationStateApi
1028 {
1029 private:
1030 auto impl() const
1031 {
1032 return static_cast<const Derived*>(this)->get();
1033 }
1034
1035 friend Derived;
1036 BlockValidationStateApi() = default;
1037
1038 public:
1039 ValidationMode GetValidationMode() const
1040 {
1041 return static_cast<ValidationMode>(btck_block_validation_state_get_validation_mode(impl()));
1042 }
1043
1044 BlockValidationResult GetBlockValidationResult() const
1045 {
1046 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 explicit BlockValidationStateView(const btck_BlockValidationState* ptr) : View{ptr} {}
1054 };
1055
1056 class BlockValidationState : public Handle<btck_BlockValidationState, btck_block_validation_state_copy, btck_block_validation_state_destroy>, public BlockValidationStateApi<BlockValidationState>
1057 {
1058 public:
1059 explicit BlockValidationState() : Handle{btck_block_validation_state_create()} {}
1060
1061 explicit BlockValidationState(const BlockValidationStateView& view) : Handle{view} {}
1062
1063 explicit BlockValidationState(btck_BlockValidationState* state) : Handle{state} {}
1064 };
1065
1066 inline bool Block::Check(const ConsensusParamsView& consensus_params,
1067 BlockCheckFlags flags,
1068 BlockValidationState& state) const
1069 {
1070 return btck_block_check(get(), consensus_params.get(), static_cast<btck_BlockCheckFlags>(flags), state.get()) == 1;
1071 }
1072
1073 class TxValidationState : public UniqueHandle<btck_TxValidationState, btck_tx_validation_state_destroy>
1074 {
1075 public:
1076 using UniqueHandle::UniqueHandle; // inherit ctor
1077 explicit TxValidationState() : UniqueHandle{btck_tx_validation_state_create()} {}
1078
1079 ValidationMode GetValidationMode() const
1080 {
1081 return static_cast<ValidationMode>(btck_tx_validation_state_get_validation_mode(get()));
1082 }
1083
1084 TxValidationResult GetTxValidationResult() const
1085 {
1086 return static_cast<TxValidationResult>(btck_tx_validation_state_get_tx_validation_result(get()));
1087 }
1088 };
1089
1090 inline bool CheckTransaction(const Transaction& tx, TxValidationState& state)
1091 {
1092 return btck_transaction_check(tx.get(), state.get()) == 1;
1093 }
1094
1095 class ValidationInterface
1096 {
1097 public:
1098 virtual ~ValidationInterface() = default;
1099
1100 virtual void BlockChecked(Block block, BlockValidationStateView state) {}
1101
1102 virtual void PowValidBlock(BlockTreeEntry entry, Block block) {}
1103
1104 virtual void BlockConnected(Block block, BlockTreeEntry entry) {}
1105
1106 virtual void BlockDisconnected(Block block, BlockTreeEntry entry) {}
1107 };
1108
1109 class ChainParams : public Handle<btck_ChainParameters, btck_chain_parameters_copy, btck_chain_parameters_destroy>
1110 {
1111 public:
1112 explicit ChainParams(ChainType chain_type)
1113 : Handle{btck_chain_parameters_create(static_cast<btck_ChainType>(chain_type))} {}
1114
1115 explicit ChainParams(std::span<const std::byte> signet_challenge)
1116 : Handle{btck_chain_parameters_create_signet(signet_challenge.data(), signet_challenge.size())} {}
1117
1118 ConsensusParamsView GetConsensusParams() const
1119 {
1120 return ConsensusParamsView{btck_chain_parameters_get_consensus_params(get())};
1121 }
1122 };
1123
1124 class ContextOptions : public UniqueHandle<btck_ContextOptions, btck_context_options_destroy>
1125 {
1126 public:
1127 ContextOptions() : UniqueHandle{btck_context_options_create()} {}
1128
1129 void SetChainParams(ChainParams& chain_params)
1130 {
1131 btck_context_options_set_chainparams(get(), chain_params.get());
1132 }
1133
1134 template <typename T>
1135 void SetNotifications(std::shared_ptr<T> notifications)
1136 {
1137 static_assert(std::is_base_of_v<KernelNotifications, T>);
1138 auto heap_notifications = std::make_unique<std::shared_ptr<T>>(std::move(notifications));
1139 using user_type = std::shared_ptr<T>*;
1140 btck_context_options_set_notifications(
1141 get(),
1142 btck_NotificationInterfaceCallbacks{
1143 .user_data = heap_notifications.release(),
1144 .user_data_destroy = +[](void* user_data) { delete static_cast<user_type>(user_data); },
1145 .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 }
1154
1155 template <typename T>
1156 void SetValidationInterface(std::shared_ptr<T> validation_interface)
1157 {
1158 static_assert(std::is_base_of_v<ValidationInterface, T>);
1159 auto heap_vi = std::make_unique<std::shared_ptr<T>>(std::move(validation_interface));
1160 using user_type = std::shared_ptr<T>*;
1161 btck_context_options_set_validation_interface(
1162 get(),
1163 btck_ValidationInterfaceCallbacks{
1164 .user_data = heap_vi.release(),
1165 .user_data_destroy = +[](void* user_data) { delete static_cast<user_type>(user_data); },
1166 .block_checked = +[](void* user_data, btck_Block* block, const btck_BlockValidationState* state) { (*static_cast<user_type>(user_data))->BlockChecked(Block{block}, BlockValidationStateView{state}); },
1167 .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 .block_connected = +[](void* user_data, btck_Block* block, const btck_BlockTreeEntry* entry) { (*static_cast<user_type>(user_data))->BlockConnected(Block{block}, BlockTreeEntry{entry}); },
1169 .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 }
1172 };
1173
1174 class Context : public Handle<btck_Context, btck_context_copy, btck_context_destroy>
1175 {
1176 public:
1177 Context(ContextOptions& opts)
1178 : Handle{btck_context_create(opts.get())} {}
1179
1180 Context()
1181 : Handle{btck_context_create(ContextOptions{}.get())} {}
1182
1183 bool interrupt()
1184 {
1185 return btck_context_interrupt(get()) == 0;
1186 }
1187 };
1188
1189 class ChainstateManagerOptions : public UniqueHandle<btck_ChainstateManagerOptions, btck_chainstate_manager_options_destroy>
1190 {
1191 public:
1192 ChainstateManagerOptions(const Context& context, std::string_view data_dir, std::string_view blocks_dir)
1193 : UniqueHandle{btck_chainstate_manager_options_create(
1194 context.get(), data_dir.data(), data_dir.length(), blocks_dir.data(), blocks_dir.length())}
1195 {
1196 }
1197
1198 void SetWorkerThreads(int worker_threads)
1199 {
1200 btck_chainstate_manager_options_set_worker_threads_num(get(), worker_threads);
1201 }
1202
1203 bool SetWipeDbs(bool wipe_block_tree, bool wipe_chainstate)
1204 {
1205 return btck_chainstate_manager_options_set_wipe_dbs(get(), wipe_block_tree, wipe_chainstate) == 0;
1206 }
1207
1208 void UpdateBlockTreeDbInMemory(bool block_tree_db_in_memory)
1209 {
1210 btck_chainstate_manager_options_update_block_tree_db_in_memory(get(), block_tree_db_in_memory);
1211 }
1212
1213 void UpdateChainstateDbInMemory(bool chainstate_db_in_memory)
1214 {
1215 btck_chainstate_manager_options_update_chainstate_db_in_memory(get(), chainstate_db_in_memory);
1216 }
1217 };
1218
1219 class ChainView : public View<btck_Chain>
1220 {
1221 public:
1222 explicit ChainView(const btck_Chain* ptr) : View{ptr} {}
1223
1224 int32_t Height() const
1225 {
1226 return btck_chain_get_height(get());
1227 }
1228
1229 int32_t CountEntries() const
1230 {
1231 return btck_chain_get_height(get()) + 1;
1232 }
1233
1234 BlockTreeEntry GetByHeight(int32_t height) const
1235 {
1236 auto index{btck_chain_get_by_height(get(), height)};
1237 if (!index) throw std::runtime_error("No entry in the chain at the provided height");
1238 return index;
1239 }
1240
1241 bool Contains(BlockTreeEntry& entry) const
1242 {
1243 return btck_chain_contains(get(), entry.get());
1244 }
1245
1246 MAKE_RANGE_METHOD(Entries, ChainView, &ChainView::CountEntries, &ChainView::GetByHeight, *this)
1247 };
1248
1249 template <typename Derived>
1250 class CoinApi
1251 {
1252 private:
1253 auto impl() const
1254 {
1255 return static_cast<const Derived*>(this)->get();
1256 }
1257
1258 friend Derived;
1259 CoinApi() = default;
1260
1261 public:
1262 uint32_t GetConfirmationHeight() const { return btck_coin_confirmation_height(impl()); }
1263
1264 bool IsCoinbase() const { return btck_coin_is_coinbase(impl()) == 1; }
1265
1266 TransactionOutputView GetOutput() const
1267 {
1268 return TransactionOutputView{btck_coin_get_output(impl())};
1269 }
1270 };
1271
1272 class CoinView : public View<btck_Coin>, public CoinApi<CoinView>
1273 {
1274 public:
1275 explicit CoinView(const btck_Coin* ptr) : View{ptr} {}
1276 };
1277
1278 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 Coin(const CoinView& view) : Handle{view} {}
1284 };
1285
1286 template <typename Derived>
1287 class TransactionSpentOutputsApi
1288 {
1289 private:
1290 auto impl() const
1291 {
1292 return static_cast<const Derived*>(this)->get();
1293 }
1294
1295 friend Derived;
1296 TransactionSpentOutputsApi() = default;
1297
1298 public:
1299 size_t Count() const
1300 {
1301 return btck_transaction_spent_outputs_count(impl());
1302 }
1303
1304 CoinView GetCoin(size_t index) const
1305 {
1306 return CoinView{btck_transaction_spent_outputs_get_coin_at(impl(), index)};
1307 }
1308
1309 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 explicit TransactionSpentOutputsView(const btck_TransactionSpentOutputs* ptr) : View{ptr} {}
1316 };
1317
1318 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 TransactionSpentOutputs(const TransactionSpentOutputsView& view) : Handle{view} {}
1325 };
1326
1327 class BlockSpentOutputs : public Handle<btck_BlockSpentOutputs, btck_block_spent_outputs_copy, btck_block_spent_outputs_destroy>
1328 {
1329 public:
1330 BlockSpentOutputs(btck_BlockSpentOutputs* block_spent_outputs)
1331 : Handle{block_spent_outputs}
1332 {
1333 }
1334
1335 size_t Count() const
1336 {
1337 return btck_block_spent_outputs_count(get());
1338 }
1339
1340 TransactionSpentOutputsView GetTxSpentOutputs(size_t tx_undo_index) const
1341 {
1342 return TransactionSpentOutputsView{btck_block_spent_outputs_get_transaction_spent_outputs_at(get(), tx_undo_index)};
1343 }
1344
1345 MAKE_RANGE_METHOD(TxsSpentOutputs, BlockSpentOutputs, &BlockSpentOutputs::Count, &BlockSpentOutputs::GetTxSpentOutputs, *this)
1346 };
1347
1348 class ChainMan : UniqueHandle<btck_ChainstateManager, btck_chainstate_manager_destroy>
1349 {
1350 public:
1351 ChainMan(const Context& context, const ChainstateManagerOptions& chainman_opts)
1352 : UniqueHandle{btck_chainstate_manager_create(chainman_opts.get())}
1353 {
1354 }
1355
1356 bool ImportBlocks(const std::span<const std::string> paths)
1357 {
1358 std::vector<const char*> c_paths;
1359 std::vector<size_t> c_paths_lens;
1360 c_paths.reserve(paths.size());
1361 c_paths_lens.reserve(paths.size());
1362 for (const auto& path : paths) {
1363 c_paths.push_back(path.c_str());
1364 c_paths_lens.push_back(path.length());
1365 }
1366
1367 return btck_chainstate_manager_import_blocks(get(), c_paths.data(), c_paths_lens.data(), c_paths.size()) == 0;
1368 }
1369
1370 bool ProcessBlock(const Block& block, bool* new_block)
1371 {
1372 int _new_block;
1373 int res = btck_chainstate_manager_process_block(get(), block.get(), &_new_block);
1374 if (new_block) *new_block = _new_block == 1;
1375 return res == 0;
1376 }
1377
1378 BlockValidationState ProcessBlockHeader(const BlockHeader& header)
1379 {
1380 auto state = btck_chainstate_manager_process_block_header(get(), header.get());
1381 return BlockValidationState{state};
1382 }
1383
1384 ChainView GetChain() const
1385 {
1386 return ChainView{btck_chainstate_manager_get_active_chain(get())};
1387 }
1388
1389 std::optional<BlockTreeEntry> GetBlockTreeEntry(const BlockHash& block_hash) const
1390 {
1391 auto entry{btck_chainstate_manager_get_block_tree_entry_by_hash(get(), block_hash.get())};
1392 if (!entry) return std::nullopt;
1393 return entry;
1394 }
1395
1396 BlockTreeEntry GetBestEntry() const
1397 {
1398 return btck_chainstate_manager_get_best_entry(get());
1399 }
1400
1401 std::optional<Block> ReadBlock(const BlockTreeEntry& entry) const
1402 {
1403 auto block{btck_block_read(get(), entry.get())};
1404 if (!block) return std::nullopt;
1405 return block;
1406 }
1407
1408 BlockSpentOutputs ReadBlockSpentOutputs(const BlockTreeEntry& entry) const
1409 {
1410 return btck_block_spent_outputs_read(get(), entry.get());
1411 }
1412 };
1413
1414 } // namespace btck
1415
1416 #endif // BITCOIN_KERNEL_BITCOINKERNEL_WRAPPER_H
1417