Skip to content

Commit 01e5d6b

Browse files
committed
Merge bitcoin/bitcoin#28048: kernel: Remove StartShutdown calls from validation code
31eca93 kernel: Remove StartShutdown calls from validation code (Ryan Ofsky) Pull request description: This change drops the last kernel dependency on shutdown.cpp. It also adds new hooks for libbitcoinkernel applications to be able to interrupt kernel operations when the chain tip changes. This change is mostly a refactoring, but does slightly change `-stopatheight` behavior (see release note and commit message) ACKs for top commit: TheCharlatan: ACK 31eca93 furszy: Concept and light review ACK 31eca93 hebasto: ACK 31eca93, I have reviewed the code and it looks OK. MarcoFalke: lgtm ACK 31eca93 🕷 Tree-SHA512: e26928436bcde658e842b1f92e9c24b1ce91031fb63b41aafccf3130bfff532b75338a269a2bb7558bff2973913f17b97a00fec3e7e0588e2ce44de097142047
2 parents 4a1aae6 + 31eca93 commit 01e5d6b

10 files changed

+55
-16
lines changed

Diff for: src/Makefile.am

-1
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,6 @@ libbitcoinkernel_la_SOURCES = \
956956
script/script_error.cpp \
957957
script/sigcache.cpp \
958958
script/standard.cpp \
959-
shutdown.cpp \
960959
signet.cpp \
961960
support/cleanse.cpp \
962961
support/lockedpool.cpp \

Diff for: src/bitcoin-chainstate.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ int main(int argc, char* argv[])
8181
class KernelNotifications : public kernel::Notifications
8282
{
8383
public:
84-
void blockTip(SynchronizationState, CBlockIndex&) override
84+
kernel::InterruptResult blockTip(SynchronizationState, CBlockIndex&) override
8585
{
8686
std::cout << "Block tip changed" << std::endl;
87+
return {};
8788
}
8889
void headerTip(SynchronizationState, int64_t height, int64_t timestamp, bool presync) override
8990
{

Diff for: src/init.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ using node::CacheSizes;
123123
using node::CalculateCacheSizes;
124124
using node::DEFAULT_PERSIST_MEMPOOL;
125125
using node::DEFAULT_PRINTPRIORITY;
126+
using node::DEFAULT_STOPATHEIGHT;
126127
using node::fReindex;
127128
using node::KernelNotifications;
128129
using node::LoadChainstate;
@@ -1408,6 +1409,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
14081409
// ********************************************************* Step 7: load block chain
14091410

14101411
node.notifications = std::make_unique<KernelNotifications>(node.exit_status);
1412+
ReadNotificationArgs(args, *node.notifications);
14111413
fReindex = args.GetBoolArg("-reindex", false);
14121414
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
14131415
ChainstateManager::Options chainman_opts{

Diff for: src/kernel/chainstatemanager_opts.h

-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class CChainParams;
2121

2222
static constexpr bool DEFAULT_CHECKPOINTS_ENABLED{true};
2323
static constexpr auto DEFAULT_MAX_TIP_AGE{24h};
24-
static constexpr int DEFAULT_STOPATHEIGHT{0};
2524

2625
namespace kernel {
2726

@@ -46,7 +45,6 @@ struct ChainstateManagerOpts {
4645
DBOptions coins_db{};
4746
CoinsViewOptions coins_view{};
4847
Notifications& notifications;
49-
int stop_at_height{DEFAULT_STOPATHEIGHT};
5048
};
5149

5250
} // namespace kernel

Diff for: src/kernel/notifications_interface.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,25 @@
99

1010
#include <cstdint>
1111
#include <string>
12+
#include <variant>
1213

1314
class CBlockIndex;
1415
enum class SynchronizationState;
1516

1617
namespace kernel {
1718

19+
//! Result type for use with std::variant to indicate that an operation should be interrupted.
20+
struct Interrupted{};
21+
22+
//! Simple result type for functions that need to propagate an interrupt status and don't have other return values.
23+
using InterruptResult = std::variant<std::monostate, Interrupted>;
24+
25+
template <typename T>
26+
bool IsInterrupted(const T& result)
27+
{
28+
return std::holds_alternative<kernel::Interrupted>(result);
29+
}
30+
1831
/**
1932
* A base class defining functions for notifying about certain kernel
2033
* events.
@@ -24,7 +37,7 @@ class Notifications
2437
public:
2538
virtual ~Notifications(){};
2639

27-
virtual void blockTip(SynchronizationState state, CBlockIndex& index) {}
40+
[[nodiscard]] virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) { return {}; }
2841
virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
2942
virtual void progress(const bilingual_str& title, int progress_percent, bool resume_possible) {}
3043
virtual void warning(const bilingual_str& warning) {}

Diff for: src/node/chainstatemanager_args.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManage
3737

3838
if (auto value{args.GetIntArg("-maxtipage")}) opts.max_tip_age = std::chrono::seconds{*value};
3939

40-
if (auto value{args.GetIntArg("-stopatheight")}) opts.stop_at_height = *value;
41-
4240
ReadDatabaseArgs(args, opts.block_tree_db);
4341
ReadDatabaseArgs(args, opts.coins_db);
4442
ReadCoinsViewArgs(args, opts.coins_view);

Diff for: src/node/kernel_notifications.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <config/bitcoin-config.h>
99
#endif
1010

11+
#include <chain.h>
1112
#include <common/args.h>
1213
#include <common/system.h>
1314
#include <kernel/context.h>
@@ -57,9 +58,14 @@ static void DoWarning(const bilingual_str& warning)
5758

5859
namespace node {
5960

60-
void KernelNotifications::blockTip(SynchronizationState state, CBlockIndex& index)
61+
kernel::InterruptResult KernelNotifications::blockTip(SynchronizationState state, CBlockIndex& index)
6162
{
6263
uiInterface.NotifyBlockTip(state, &index);
64+
if (m_stop_at_height && index.nHeight >= m_stop_at_height) {
65+
StartShutdown();
66+
return kernel::Interrupted{};
67+
}
68+
return {};
6369
}
6470

6571
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
8793
node::AbortNode(m_exit_status, debug_message, user_message, m_shutdown_on_fatal_error);
8894
}
8995

96+
void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications)
97+
{
98+
if (auto value{args.GetIntArg("-stopatheight")}) notifications.m_stop_at_height = *value;
99+
}
100+
90101
} // namespace node

Diff for: src/node/kernel_notifications.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@
1111
#include <cstdint>
1212
#include <string>
1313

14+
class ArgsManager;
1415
class CBlockIndex;
1516
enum class SynchronizationState;
1617
struct bilingual_str;
1718

1819
namespace node {
20+
21+
static constexpr int DEFAULT_STOPATHEIGHT{0};
22+
1923
class KernelNotifications : public kernel::Notifications
2024
{
2125
public:
2226
KernelNotifications(std::atomic<int>& exit_status) : m_exit_status{exit_status} {}
2327

24-
void blockTip(SynchronizationState state, CBlockIndex& index) override;
28+
[[nodiscard]] kernel::InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) override;
2529

2630
void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override;
2731

@@ -33,11 +37,16 @@ class KernelNotifications : public kernel::Notifications
3337

3438
void fatalError(const std::string& debug_message, const bilingual_str& user_message = {}) override;
3539

40+
//! Block height after which blockTip notification will return Interrupted{}, if >0.
41+
int m_stop_at_height{DEFAULT_STOPATHEIGHT};
3642
//! Useful for tests, can be set to false to avoid shutdown on fatal error.
3743
bool m_shutdown_on_fatal_error{true};
3844
private:
3945
std::atomic<int>& m_exit_status;
4046
};
47+
48+
void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications);
49+
4150
} // namespace node
4251

4352
#endif // BITCOIN_NODE_KERNEL_NOTIFICATIONS_H

Diff for: src/validation.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include <reverse_iterator.h>
3838
#include <script/script.h>
3939
#include <script/sigcache.h>
40-
#include <shutdown.h>
4140
#include <signet.h>
4241
#include <tinyformat.h>
4342
#include <txdb.h>
@@ -3172,13 +3171,17 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
31723171
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
31733172

31743173
// Always notify the UI if a new block tip was connected
3175-
m_chainman.GetNotifications().blockTip(GetSynchronizationState(fInitialDownload), *pindexNewTip);
3174+
if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(fInitialDownload), *pindexNewTip))) {
3175+
// Just breaking and returning success for now. This could
3176+
// be changed to bubble up the kernel::Interrupted value to
3177+
// the caller so the caller could distinguish between
3178+
// completed and interrupted operations.
3179+
break;
3180+
}
31763181
}
31773182
}
31783183
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
31793184

3180-
if (m_chainman.StopAtHeight() && pindexNewTip && pindexNewTip->nHeight >= m_chainman.StopAtHeight()) StartShutdown();
3181-
31823185
if (WITH_LOCK(::cs_main, return m_disabled)) {
31833186
// Background chainstate has reached the snapshot base block, so exit.
31843187
break;
@@ -3369,7 +3372,14 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
33693372

33703373
// Only notify about a new block tip if the active chain was modified.
33713374
if (pindex_was_in_chain) {
3372-
m_chainman.GetNotifications().blockTip(GetSynchronizationState(IsInitialBlockDownload()), *to_mark_failed->pprev);
3375+
// Ignoring return value for now, this could be changed to bubble up
3376+
// kernel::Interrupted value to the caller so the caller could
3377+
// distinguish between completed and interrupted operations. It might
3378+
// also make sense for the blockTip notification to have an enum
3379+
// parameter indicating the source of the tip change so hooks can
3380+
// distinguish user-initiated invalidateblock changes from other
3381+
// changes.
3382+
(void)m_chainman.GetNotifications().blockTip(GetSynchronizationState(IsInitialBlockDownload()), *to_mark_failed->pprev);
33733383
}
33743384
return true;
33753385
}

Diff for: src/validation.h

-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <policy/packages.h>
2424
#include <policy/policy.h>
2525
#include <script/script_error.h>
26-
#include <shutdown.h>
2726
#include <sync.h>
2827
#include <txdb.h>
2928
#include <txmempool.h> // For CTxMemPool::cs
@@ -970,7 +969,6 @@ class ChainstateManager
970969
const arith_uint256& MinimumChainWork() const { return *Assert(m_options.minimum_chain_work); }
971970
const uint256& AssumedValidBlock() const { return *Assert(m_options.assumed_valid_block); }
972971
kernel::Notifications& GetNotifications() const { return m_options.notifications; };
973-
int StopAtHeight() const { return m_options.stop_at_height; };
974972

975973
/**
976974
* Alias for ::cs_main.

0 commit comments

Comments
 (0)