Merge 01e5d6b105 into merged_master (Bitcoin PR bitcoin/bitcoin#28048)

This commit is contained in:
Byron Hambly 2025-07-01 13:02:51 +02:00
commit e17c92ebb1
10 changed files with 56 additions and 17 deletions

View file

@ -1039,7 +1039,6 @@ libbitcoinkernel_la_SOURCES = \
script/script_error.cpp \
script/sigcache.cpp \
script/standard.cpp \
shutdown.cpp \
signet.cpp \
support/cleanse.cpp \
support/lockedpool.cpp \

View file

@ -81,9 +81,10 @@ int main(int argc, char* argv[])
class KernelNotifications : public kernel::Notifications
{
public:
void blockTip(SynchronizationState, CBlockIndex&) override
kernel::InterruptResult blockTip(SynchronizationState, CBlockIndex&) override
{
std::cout << "Block tip changed" << std::endl;
return {};
}
void headerTip(SynchronizationState, int64_t height, int64_t timestamp, bool presync) override
{

View file

@ -127,6 +127,7 @@ using node::CacheSizes;
using node::CalculateCacheSizes;
using node::DEFAULT_PERSIST_MEMPOOL;
using node::DEFAULT_PRINTPRIORITY;
using node::DEFAULT_STOPATHEIGHT;
using node::fReindex;
using node::KernelNotifications;
using node::LoadChainstate;
@ -1548,6 +1549,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// ********************************************************* Step 7: load block chain
node.notifications = std::make_unique<KernelNotifications>(node.exit_status);
ReadNotificationArgs(args, *node.notifications);
fReindex = args.GetBoolArg("-reindex", false);
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
ChainstateManager::Options chainman_opts{

View file

@ -21,7 +21,6 @@ class CChainParams;
static constexpr bool DEFAULT_CHECKPOINTS_ENABLED{true};
static constexpr auto DEFAULT_MAX_TIP_AGE{24h};
static constexpr int DEFAULT_STOPATHEIGHT{0};
namespace kernel {
@ -46,7 +45,6 @@ struct ChainstateManagerOpts {
DBOptions coins_db{};
CoinsViewOptions coins_view{};
Notifications& notifications;
int stop_at_height{DEFAULT_STOPATHEIGHT};
};
} // namespace kernel

View file

@ -9,12 +9,25 @@
#include <cstdint>
#include <string>
#include <variant>
class CBlockIndex;
enum class SynchronizationState;
namespace kernel {
//! Result type for use with std::variant to indicate that an operation should be interrupted.
struct Interrupted{};
//! Simple result type for functions that need to propagate an interrupt status and don't have other return values.
using InterruptResult = std::variant<std::monostate, Interrupted>;
template <typename T>
bool IsInterrupted(const T& result)
{
return std::holds_alternative<kernel::Interrupted>(result);
}
/**
* A base class defining functions for notifying about certain kernel
* events.
@ -24,7 +37,7 @@ class Notifications
public:
virtual ~Notifications(){};
virtual void blockTip(SynchronizationState state, CBlockIndex& index) {}
[[nodiscard]] virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) { return {}; }
virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
virtual void progress(const bilingual_str& title, int progress_percent, bool resume_possible) {}
virtual void warning(const bilingual_str& warning) {}

View file

@ -37,8 +37,6 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManage
if (auto value{args.GetIntArg("-maxtipage")}) opts.max_tip_age = std::chrono::seconds{*value};
if (auto value{args.GetIntArg("-stopatheight")}) opts.stop_at_height = *value;
ReadDatabaseArgs(args, opts.block_tree_db);
ReadDatabaseArgs(args, opts.coins_db);
ReadCoinsViewArgs(args, opts.coins_view);

View file

@ -8,6 +8,7 @@
#include <config/bitcoin-config.h>
#endif
#include <chain.h>
#include <common/args.h>
#include <common/system.h>
#include <kernel/context.h>
@ -57,9 +58,14 @@ static void DoWarning(const bilingual_str& warning)
namespace node {
void KernelNotifications::blockTip(SynchronizationState state, CBlockIndex& index)
kernel::InterruptResult KernelNotifications::blockTip(SynchronizationState state, CBlockIndex& index)
{
uiInterface.NotifyBlockTip(state, &index);
if (m_stop_at_height && index.nHeight >= m_stop_at_height) {
StartShutdown();
return kernel::Interrupted{};
}
return {};
}
void KernelNotifications::headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync)
@ -87,4 +93,9 @@ void KernelNotifications::fatalError(const std::string& debug_message, const bil
node::AbortNode(m_exit_status, debug_message, user_message, m_shutdown_on_fatal_error);
}
void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications)
{
if (auto value{args.GetIntArg("-stopatheight")}) notifications.m_stop_at_height = *value;
}
} // namespace node

View file

@ -11,17 +11,21 @@
#include <cstdint>
#include <string>
class ArgsManager;
class CBlockIndex;
enum class SynchronizationState;
struct bilingual_str;
namespace node {
static constexpr int DEFAULT_STOPATHEIGHT{0};
class KernelNotifications : public kernel::Notifications
{
public:
KernelNotifications(std::atomic<int>& exit_status) : m_exit_status{exit_status} {}
void blockTip(SynchronizationState state, CBlockIndex& index) override;
[[nodiscard]] kernel::InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) override;
void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override;
@ -33,11 +37,16 @@ public:
void fatalError(const std::string& debug_message, const bilingual_str& user_message = {}) override;
//! Block height after which blockTip notification will return Interrupted{}, if >0.
int m_stop_at_height{DEFAULT_STOPATHEIGHT};
//! Useful for tests, can be set to false to avoid shutdown on fatal error.
bool m_shutdown_on_fatal_error{true};
private:
std::atomic<int>& m_exit_status;
};
void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications);
} // namespace node
#endif // BITCOIN_NODE_KERNEL_NOTIFICATIONS_H

View file

@ -40,7 +40,6 @@
#include <reverse_iterator.h>
#include <script/script.h>
#include <script/sigcache.h>
#include <shutdown.h>
#include <signet.h>
#include <timedata.h>
#include <tinyformat.h>
@ -2769,7 +2768,7 @@ bool Chainstate::FlushStateToDisk(
if (m_chainman.m_best_header && (uint64_t)m_chainman.m_best_header->nHeight > node::nMustKeepFullHeaders) { // check first, to prevent underflow
trim_height = m_chainman.m_best_header->nHeight - node::nMustKeepFullHeaders;
}
if (node::fTrimHeaders && trim_height > 0 && !ShutdownRequested()) {
if (node::fTrimHeaders && trim_height > 0) {
static int nMinTrimHeight{0};
LogPrintf("Flushing block index, trimming headers, setTrimmableBlockIndex.size(): %d\n", setTrimmableBlockIndex.size());
for (std::set<CBlockIndex*>::iterator it = setTrimmableBlockIndex.begin(); it != setTrimmableBlockIndex.end(); it++) {
@ -3505,7 +3504,13 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
// Always notify the UI if a new block tip was connected
m_chainman.GetNotifications().blockTip(GetSynchronizationState(fInitialDownload), *pindexNewTip);
if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(fInitialDownload), *pindexNewTip))) {
// Just breaking and returning success for now. This could
// be changed to bubble up the kernel::Interrupted value to
// the caller so the caller could distinguish between
// completed and interrupted operations.
break;
}
}
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
@ -3515,8 +3520,6 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
break;
}
if (m_chainman.StopAtHeight() && pindexNewTip && pindexNewTip->nHeight >= m_chainman.StopAtHeight()) StartShutdown();
if (WITH_LOCK(::cs_main, return m_disabled)) {
// Background chainstate has reached the snapshot base block, so exit.
break;
@ -3707,7 +3710,14 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
// Only notify about a new block tip if the active chain was modified.
if (pindex_was_in_chain) {
m_chainman.GetNotifications().blockTip(GetSynchronizationState(IsInitialBlockDownload()), *to_mark_failed->pprev);
// Ignoring return value for now, this could be changed to bubble up
// kernel::Interrupted value to the caller so the caller could
// distinguish between completed and interrupted operations. It might
// also make sense for the blockTip notification to have an enum
// parameter indicating the source of the tip change so hooks can
// distinguish user-initiated invalidateblock changes from other
// changes.
(void)m_chainman.GetNotifications().blockTip(GetSynchronizationState(IsInitialBlockDownload()), *to_mark_failed->pprev);
}
return true;
}

View file

@ -24,7 +24,6 @@
#include <policy/packages.h>
#include <policy/policy.h>
#include <script/script_error.h>
#include <shutdown.h>
#include <sync.h>
#include <txdb.h>
#include <txmempool.h> // For CTxMemPool::cs
@ -980,7 +979,6 @@ public:
const arith_uint256& MinimumChainWork() const { return *Assert(m_options.minimum_chain_work); }
const uint256& AssumedValidBlock() const { return *Assert(m_options.assumed_valid_block); }
kernel::Notifications& GetNotifications() const { return m_options.notifications; };
int StopAtHeight() const { return m_options.stop_at_height; };
/**
* Alias for ::cs_main.