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