Skip to content

Commit 050fa0e

Browse files
committed
patch: Enhance snapshot loading with progress notifications
- Implemented a new method `snapshotLoadProgress(double progress)` in the notifications interface to report loading progress of UTXO snapshots. - Updated `ChainstateManager::PopulateAndValidateSnapshot` to calculate and send progress updates during snapshot loading. - Introduced a new signal `SnapshotLoadProgress` in the UI interface for handling progress notifications. - Added necessary handlers in the node interface to connect the new progress signal. - Included a patch file for clean CI environments to ensure consistent submodule state.
1 parent 933bd46 commit 050fa0e

File tree

3 files changed

+217
-1
lines changed

3 files changed

+217
-1
lines changed

CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,30 @@ set(BUILD_WALLET_TOOL OFF)
5151
set(BUILD_GUI ON)
5252
set(ENABLE_WALLET ON)
5353

54+
# Always reset and apply the patch for clean CI environments
55+
set(SUBMODULE_PATCH_FILE "${CMAKE_SOURCE_DIR}/patch/0746cc67-snapshot-load-progress.patch")
56+
57+
if(EXISTS "${SUBMODULE_PATCH_FILE}")
58+
message(STATUS "Resetting bitcoin submodule to clean state...")
59+
execute_process(
60+
COMMAND git reset --hard HEAD
61+
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bitcoin
62+
)
63+
64+
message(STATUS "Applying patch to bitcoin submodule...")
65+
execute_process(
66+
COMMAND git apply "${SUBMODULE_PATCH_FILE}"
67+
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bitcoin
68+
RESULT_VARIABLE PATCH_RESULT
69+
OUTPUT_VARIABLE PATCH_OUTPUT
70+
ERROR_VARIABLE PATCH_ERROR
71+
)
72+
73+
if(NOT PATCH_RESULT EQUAL 0)
74+
message(FATAL_ERROR "Failed to apply submodule patch:\n${PATCH_ERROR}")
75+
endif()
76+
endif()
77+
5478
# Bitcoin Core codebase
5579
# Builds libraries: univalue, core_interface, bitcoin_node, bitcoin_wallet
5680
add_subdirectory(bitcoin)

bitcoin

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
From 0746cc67eb84402b26fb381e5c9c9e1605c7f2ab Mon Sep 17 00:00:00 2001
2+
From: D33r-Gee <[email protected]>
3+
Date: Tue, 29 Jul 2025 11:11:16 -0700
4+
Subject: [PATCH] cpp: Implement snapshot loading progress notifications
5+
6+
- Added a new method `snapshotLoadProgress(double progress)` to the notifications interface to report the progress of loading UTXO snapshots.
7+
- Updated the `ChainstateManager::PopulateAndValidateSnapshot` function to calculate and send progress updates during the snapshot loading process.
8+
- Introduced a new signal `SnapshotLoadProgress` in the UI interface to handle progress notifications.
9+
- Implemented the necessary handlers in the node interface to connect the new progress signal.
10+
11+
This enhancement improves user feedback during lengthy snapshot loading operations.
12+
---
13+
src/interfaces/node.h | 9 +++++++++
14+
src/kernel/notifications_interface.h | 1 +
15+
src/node/interface_ui.cpp | 3 +++
16+
src/node/interface_ui.h | 3 +++
17+
src/node/interfaces.cpp | 10 ++++++++++
18+
src/node/kernel_notifications.cpp | 5 +++++
19+
src/node/kernel_notifications.h | 2 ++
20+
src/validation.cpp | 4 ++++
21+
8 files changed, 37 insertions(+)
22+
23+
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
24+
index 78a186c5d9..0ff267e484 100644
25+
--- a/src/interfaces/node.h
26+
+++ b/src/interfaces/node.h
27+
@@ -12,6 +12,7 @@
28+
#include <net_types.h>
29+
#include <netaddress.h>
30+
#include <netbase.h>
31+
+#include <node/utxo_snapshot.h>
32+
#include <support/allocators/secure.h>
33+
#include <util/translation.h>
34+
35+
@@ -204,6 +205,10 @@ public:
36+
//! List rpc commands.
37+
virtual std::vector<std::string> listRpcCommands() = 0;
38+
39+
+
40+
+ //! Load UTXO Snapshot.
41+
+ virtual bool loadSnapshot(AutoFile& afile, const node::SnapshotMetadata& metadata, bool in_memory) = 0;
42+
+
43+
//! Get unspent output associated with a transaction.
44+
virtual std::optional<Coin> getUnspentOutput(const COutPoint& output) = 0;
45+
46+
@@ -233,6 +238,10 @@ public:
47+
using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>;
48+
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
49+
50+
+ //! Register handler for snapshot load progress.
51+
+ using SnapshotLoadProgressFn = std::function<void(double progress)>;
52+
+ virtual std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) = 0;
53+
+
54+
//! Register handler for wallet loader constructed messages.
55+
using InitWalletFn = std::function<void()>;
56+
virtual std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) = 0;
57+
diff --git a/src/kernel/notifications_interface.h b/src/kernel/notifications_interface.h
58+
index 3e97e3b45e..e6a5a1dd3f 100644
59+
--- a/src/kernel/notifications_interface.h
60+
+++ b/src/kernel/notifications_interface.h
61+
@@ -40,6 +40,7 @@ public:
62+
[[nodiscard]] virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex& index, double verification_progress) { return {}; }
63+
virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
64+
virtual void progress(const bilingual_str& title, int progress_percent, bool resume_possible) {}
65+
+ virtual void snapshotLoadProgress(double progress) {}
66+
virtual void warningSet(Warning id, const bilingual_str& message) {}
67+
virtual void warningUnset(Warning id) {}
68+
69+
diff --git a/src/node/interface_ui.cpp b/src/node/interface_ui.cpp
70+
index 273e51974e..3d6a705db7 100644
71+
--- a/src/node/interface_ui.cpp
72+
+++ b/src/node/interface_ui.cpp
73+
@@ -23,6 +23,7 @@ struct UISignals {
74+
boost::signals2::signal<CClientUIInterface::NotifyNetworkActiveChangedSig> NotifyNetworkActiveChanged;
75+
boost::signals2::signal<CClientUIInterface::NotifyAlertChangedSig> NotifyAlertChanged;
76+
boost::signals2::signal<CClientUIInterface::ShowProgressSig> ShowProgress;
77+
+ boost::signals2::signal<CClientUIInterface::SnapshotLoadProgressSig> SnapshotLoadProgress;
78+
boost::signals2::signal<CClientUIInterface::NotifyBlockTipSig> NotifyBlockTip;
79+
boost::signals2::signal<CClientUIInterface::NotifyHeaderTipSig> NotifyHeaderTip;
80+
boost::signals2::signal<CClientUIInterface::BannedListChangedSig> BannedListChanged;
81+
@@ -46,6 +47,7 @@ ADD_SIGNALS_IMPL_WRAPPER(ShowProgress);
82+
ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip);
83+
ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip);
84+
ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged);
85+
+ADD_SIGNALS_IMPL_WRAPPER(SnapshotLoadProgress);
86+
87+
bool CClientUIInterface::ThreadSafeMessageBox(const bilingual_str& message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style).value_or(false);}
88+
bool CClientUIInterface::ThreadSafeQuestion(const bilingual_str& message, const std::string& non_interactive_message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style).value_or(false);}
89+
@@ -55,6 +57,7 @@ void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { re
90+
void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); }
91+
void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
92+
void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
93+
+void CClientUIInterface::SnapshotLoadProgress(double progress) { return g_ui_signals.SnapshotLoadProgress(progress); }
94+
void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex& block, double verification_progress) { return g_ui_signals.NotifyBlockTip(s, block, verification_progress); }
95+
void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, int64_t height, int64_t timestamp, bool presync) { return g_ui_signals.NotifyHeaderTip(s, height, timestamp, presync); }
96+
void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }
97+
diff --git a/src/node/interface_ui.h b/src/node/interface_ui.h
98+
index 7732cf4797..6f25870c49 100644
99+
--- a/src/node/interface_ui.h
100+
+++ b/src/node/interface_ui.h
101+
@@ -102,6 +102,9 @@ public:
102+
*/
103+
ADD_SIGNALS_DECL_WRAPPER(ShowProgress, void, const std::string& title, int nProgress, bool resume_possible);
104+
105+
+ /** Snapshot load progress. */
106+
+ ADD_SIGNALS_DECL_WRAPPER(SnapshotLoadProgress, void, double progress);
107+
+
108+
/** New block has been accepted */
109+
ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, SynchronizationState, const CBlockIndex& block, double verification_progress);
110+
111+
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
112+
index 0485ff48bd..f02e1d28cd 100644
113+
--- a/src/node/interfaces.cpp
114+
+++ b/src/node/interfaces.cpp
115+
@@ -38,6 +38,7 @@
116+
#include <node/kernel_notifications.h>
117+
#include <node/transaction.h>
118+
#include <node/types.h>
119+
+#include <node/utxo_snapshot.h>
120+
#include <node/warnings.h>
121+
#include <policy/feerate.h>
122+
#include <policy/fees.h>
123+
@@ -361,6 +362,11 @@ public:
124+
LOCK(::cs_main);
125+
return chainman().ActiveChainstate().CoinsTip().GetCoin(output);
126+
}
127+
+ bool loadSnapshot(AutoFile& coins_file, const SnapshotMetadata& metadata, bool in_memory) override
128+
+ {
129+
+ auto activation_result{chainman().ActivateSnapshot(coins_file, metadata, in_memory)};
130+
+ return activation_result.has_value();
131+
+ }
132+
TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, std::string& err_string) override
133+
{
134+
return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false);
135+
@@ -385,6 +391,10 @@ public:
136+
{
137+
return MakeSignalHandler(::uiInterface.ShowProgress_connect(fn));
138+
}
139+
+ std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) override
140+
+ {
141+
+ return MakeSignalHandler(::uiInterface.SnapshotLoadProgress_connect(fn));
142+
+ }
143+
std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override
144+
{
145+
return MakeSignalHandler(::uiInterface.InitWallet_connect(fn));
146+
diff --git a/src/node/kernel_notifications.cpp b/src/node/kernel_notifications.cpp
147+
index 4a6f8444da..a1ae75ecc4 100644
148+
--- a/src/node/kernel_notifications.cpp
149+
+++ b/src/node/kernel_notifications.cpp
150+
@@ -77,6 +77,11 @@ void KernelNotifications::progress(const bilingual_str& title, int progress_perc
151+
uiInterface.ShowProgress(title.translated, progress_percent, resume_possible);
152+
}
153+
154+
+void KernelNotifications::snapshotLoadProgress(double progress)
155+
+{
156+
+ uiInterface.SnapshotLoadProgress(progress);
157+
+}
158+
+
159+
void KernelNotifications::warningSet(kernel::Warning id, const bilingual_str& message)
160+
{
161+
if (m_warnings.Set(id, message)) {
162+
diff --git a/src/node/kernel_notifications.h b/src/node/kernel_notifications.h
163+
index 10ee3e18d7..d873d34feb 100644
164+
--- a/src/node/kernel_notifications.h
165+
+++ b/src/node/kernel_notifications.h
166+
@@ -41,6 +41,8 @@ public:
167+
168+
void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override;
169+
170+
+ void snapshotLoadProgress(double progress) override;
171+
+
172+
void warningSet(kernel::Warning id, const bilingual_str& message) override;
173+
174+
void warningUnset(kernel::Warning id) override;
175+
diff --git a/src/validation.cpp b/src/validation.cpp
176+
index 3cfcd2728c..aa7cdf1c69 100644
177+
--- a/src/validation.cpp
178+
+++ b/src/validation.cpp
179+
@@ -5959,6 +5959,10 @@ util::Result<void> ChainstateManager::PopulateAndValidateSnapshot(
180+
--coins_left;
181+
++coins_processed;
182+
183+
+ // Show Snapshot Loading progress
184+
+ double progress = static_cast<double>(coins_processed) / static_cast<double>(coins_count);
185+
+ GetNotifications().snapshotLoadProgress(progress);
186+
+
187+
if (coins_processed % 1000000 == 0) {
188+
LogPrintf("[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
189+
coins_processed,
190+
--
191+
2.34.1
192+

0 commit comments

Comments
 (0)