/ src / node / kernel_notifications.cpp
kernel_notifications.cpp
  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  #include <node/kernel_notifications.h>
  6  
  7  #include <bitcoin-build-config.h> // IWYU pragma: keep
  8  
  9  #include <chain.h>
 10  #include <common/args.h>
 11  #include <common/system.h>
 12  #include <kernel/context.h>
 13  #include <kernel/warning.h>
 14  #include <logging.h>
 15  #include <node/abort.h>
 16  #include <node/interface_ui.h>
 17  #include <node/warnings.h>
 18  #include <util/check.h>
 19  #include <util/signalinterrupt.h>
 20  #include <util/strencodings.h>
 21  #include <util/string.h>
 22  #include <util/translation.h>
 23  
 24  #include <cstdint>
 25  #include <string>
 26  #include <thread>
 27  
 28  using util::ReplaceAll;
 29  
 30  static void AlertNotify(const std::string& strMessage)
 31  {
 32  #if HAVE_SYSTEM
 33      std::string strCmd = gArgs.GetArg("-alertnotify", "");
 34      if (strCmd.empty()) return;
 35  
 36      // Alert text should be plain ascii coming from a trusted source, but to
 37      // be safe we first strip anything not in safeChars, then add single quotes around
 38      // the whole string before passing it to the shell:
 39      std::string singleQuote("'");
 40      std::string safeStatus = SanitizeString(strMessage);
 41      safeStatus = singleQuote+safeStatus+singleQuote;
 42      ReplaceAll(strCmd, "%s", safeStatus);
 43  
 44      std::thread t(runCommand, strCmd);
 45      t.detach(); // thread runs free
 46  #endif
 47  }
 48  
 49  namespace node {
 50  
 51  kernel::InterruptResult KernelNotifications::blockTip(SynchronizationState state, const CBlockIndex& index, double verification_progress)
 52  {
 53      {
 54          LOCK(m_tip_block_mutex);
 55          Assume(index.GetBlockHash() != uint256::ZERO);
 56          m_state.tip_block = index.GetBlockHash();
 57          m_tip_block_cv.notify_all();
 58      }
 59  
 60      uiInterface.NotifyBlockTip(state, index, verification_progress);
 61      if (m_stop_at_height && index.nHeight >= m_stop_at_height) {
 62          if (!m_shutdown_request()) {
 63              LogError("Failed to send shutdown signal after reaching stop height\n");
 64          }
 65          return kernel::Interrupted{};
 66      }
 67      return {};
 68  }
 69  
 70  void KernelNotifications::headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync)
 71  {
 72      uiInterface.NotifyHeaderTip(state, height, timestamp, presync);
 73  }
 74  
 75  void KernelNotifications::progress(const bilingual_str& title, int progress_percent, bool resume_possible)
 76  {
 77      uiInterface.ShowProgress(title.translated, progress_percent, resume_possible);
 78  }
 79  
 80  void KernelNotifications::warningSet(kernel::Warning id, const bilingual_str& message)
 81  {
 82      if (m_warnings.Set(id, message)) {
 83          AlertNotify(message.original);
 84      }
 85  }
 86  
 87  void KernelNotifications::warningUnset(kernel::Warning id)
 88  {
 89      m_warnings.Unset(id);
 90  }
 91  
 92  void KernelNotifications::flushError(const bilingual_str& message)
 93  {
 94      AbortNode(m_shutdown_request, m_exit_status, message, &m_warnings);
 95  }
 96  
 97  void KernelNotifications::fatalError(const bilingual_str& message)
 98  {
 99      node::AbortNode(m_shutdown_on_fatal_error ? m_shutdown_request : nullptr,
100                      m_exit_status, message, &m_warnings);
101  }
102  
103  std::optional<uint256> KernelNotifications::TipBlock()
104  {
105      AssertLockHeld(m_tip_block_mutex);
106      return m_state.tip_block;
107  };
108  
109  
110  void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications)
111  {
112      if (auto value{args.GetIntArg("-stopatheight")}) notifications.m_stop_at_height = *value;
113  }
114  
115  } // namespace node