kernel_notifications.h raw

   1  // Copyright (c) 2023-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_NODE_KERNEL_NOTIFICATIONS_H
   6  #define BITCOIN_NODE_KERNEL_NOTIFICATIONS_H
   7  
   8  #include <kernel/notifications_interface.h>
   9  
  10  #include <sync.h>
  11  #include <uint256.h>
  12  
  13  #include <atomic>
  14  #include <cstdint>
  15  #include <functional>
  16  
  17  class ArgsManager;
  18  class CBlockIndex;
  19  enum class SynchronizationState;
  20  struct bilingual_str;
  21  
  22  namespace kernel {
  23  enum class Warning;
  24  } // namespace kernel
  25  
  26  namespace node {
  27  
  28  class Warnings;
  29  static constexpr int DEFAULT_STOPATHEIGHT{0};
  30  
  31  //! State tracked by the KernelNotifications interface meant to be used by
  32  //! mining code, index code, RPCs, and other code sitting above the validation
  33  //! layer.
  34  //!
  35  //! Currently just tracks the chain tip, but could be used to hold other
  36  //! information in the future, like the last flushed block, pruning
  37  //! information, etc.
  38  struct KernelState {
  39      bool chainstate_loaded{false};
  40      std::optional<uint256> tip_block;
  41  };
  42  
  43  class KernelNotifications : public kernel::Notifications
  44  {
  45  public:
  46      KernelNotifications(const std::function<bool()>& shutdown_request, std::atomic<int>& exit_status, node::Warnings& warnings)
  47          : m_shutdown_request(shutdown_request), m_exit_status{exit_status}, m_warnings{warnings} {}
  48  
  49      [[nodiscard]] kernel::InterruptResult blockTip(SynchronizationState state, const CBlockIndex& index, double verification_progress) override EXCLUSIVE_LOCKS_REQUIRED(!m_tip_block_mutex);
  50  
  51      void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override;
  52  
  53      void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override;
  54  
  55      void warningSet(kernel::Warning id, const bilingual_str& message) override;
  56  
  57      void warningUnset(kernel::Warning id) override;
  58  
  59      void flushError(const bilingual_str& message) override;
  60  
  61      void fatalError(const bilingual_str& message) override;
  62  
  63      void setChainstateLoaded(bool chainstate_loaded) EXCLUSIVE_LOCKS_REQUIRED(!m_tip_block_mutex) {
  64          LOCK(m_tip_block_mutex);
  65          if (!chainstate_loaded) m_state = {};
  66          m_state.chainstate_loaded = chainstate_loaded;
  67          m_tip_block_cv.notify_all();
  68      }
  69  
  70      //! Block height after which blockTip notification will return Interrupted{}, if >0.
  71      int m_stop_at_height{DEFAULT_STOPATHEIGHT};
  72      //! Useful for tests, can be set to false to avoid shutdown on fatal error.
  73      bool m_shutdown_on_fatal_error{true};
  74  
  75      Mutex m_tip_block_mutex;
  76      std::condition_variable m_tip_block_cv GUARDED_BY(m_tip_block_mutex);
  77      KernelState m_state GUARDED_BY(m_tip_block_mutex);
  78      //! The block for which the last blockTip notification was received.
  79      //! It's first set when the tip is connected during node initialization.
  80      //! Might be unset during an early shutdown.
  81      std::optional<uint256> TipBlock() EXCLUSIVE_LOCKS_REQUIRED(m_tip_block_mutex);
  82  
  83  private:
  84      const std::function<bool()>& m_shutdown_request;
  85      std::atomic<int>& m_exit_status;
  86      node::Warnings& m_warnings;
  87  };
  88  
  89  void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications);
  90  
  91  } // namespace node
  92  
  93  #endif // BITCOIN_NODE_KERNEL_NOTIFICATIONS_H
  94