Skip to content

Commit 25bfc72

Browse files
committed
poc: Add notification handler to display UTXO snapshot Load Progress
This serves as a quick and dirty POC to display a progress bar when an AssumeUTXO snapshot is loading. The gui code is by no means production or deployment ready. For backend evaluation pruposes only...
1 parent 2689785 commit 25bfc72

10 files changed

+72
-21
lines changed

src/interfaces/node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ class Node
244244
using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>;
245245
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
246246

247+
//! Register handler for snapshot load progress.
248+
using SnapshotLoadProgressFn = std::function<void(double progress)>;
249+
virtual std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) = 0;
250+
247251
//! Register handler for wallet loader constructed messages.
248252
using InitWalletFn = std::function<void()>;
249253
virtual std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) = 0;

src/kernel/notifications_interface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Notifications
4040
[[nodiscard]] virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) { return {}; }
4141
virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
4242
virtual void progress(const bilingual_str& title, int progress_percent, bool resume_possible) {}
43+
virtual void snapshotLoadProgress(double progress) {}
4344
virtual void warningSet(Warning id, const bilingual_str& message) {}
4445
virtual void warningUnset(Warning id) {}
4546

src/node/interface_ui.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct UISignals {
2323
boost::signals2::signal<CClientUIInterface::NotifyNetworkActiveChangedSig> NotifyNetworkActiveChanged;
2424
boost::signals2::signal<CClientUIInterface::NotifyAlertChangedSig> NotifyAlertChanged;
2525
boost::signals2::signal<CClientUIInterface::ShowProgressSig> ShowProgress;
26+
boost::signals2::signal<CClientUIInterface::SnapshotLoadProgressSig> SnapshotLoadProgress;
2627
boost::signals2::signal<CClientUIInterface::NotifyBlockTipSig> NotifyBlockTip;
2728
boost::signals2::signal<CClientUIInterface::NotifyHeaderTipSig> NotifyHeaderTip;
2829
boost::signals2::signal<CClientUIInterface::BannedListChangedSig> BannedListChanged;
@@ -43,6 +44,7 @@ ADD_SIGNALS_IMPL_WRAPPER(NotifyNumConnectionsChanged);
4344
ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkActiveChanged);
4445
ADD_SIGNALS_IMPL_WRAPPER(NotifyAlertChanged);
4546
ADD_SIGNALS_IMPL_WRAPPER(ShowProgress);
47+
ADD_SIGNALS_IMPL_WRAPPER(SnapshotLoadProgress);
4648
ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip);
4749
ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip);
4850
ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged);
@@ -55,6 +57,7 @@ void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { re
5557
void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); }
5658
void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
5759
void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
60+
void CClientUIInterface::SnapshotLoadProgress(double progress) { return g_ui_signals.SnapshotLoadProgress(progress); }
5861
void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); }
5962
void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, int64_t height, int64_t timestamp, bool presync) { return g_ui_signals.NotifyHeaderTip(s, height, timestamp, presync); }
6063
void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }

src/node/interface_ui.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ class CClientUIInterface
102102
*/
103103
ADD_SIGNALS_DECL_WRAPPER(ShowProgress, void, const std::string& title, int nProgress, bool resume_possible);
104104

105+
/** Snapshot load progress. */
106+
ADD_SIGNALS_DECL_WRAPPER(SnapshotLoadProgress, void, double progress);
107+
105108
/** New block has been accepted */
106109
ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, SynchronizationState, const CBlockIndex*);
107110

src/node/interfaces.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,10 @@ class NodeImpl : public Node
391391
{
392392
return MakeSignalHandler(::uiInterface.ShowProgress_connect(fn));
393393
}
394+
std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) override
395+
{
396+
return MakeSignalHandler(::uiInterface.SnapshotLoadProgress_connect(fn));
397+
}
394398
std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override
395399
{
396400
return MakeSignalHandler(::uiInterface.InitWallet_connect(fn));

src/node/kernel_notifications.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ void KernelNotifications::progress(const bilingual_str& title, int progress_perc
7777
uiInterface.ShowProgress(title.translated, progress_percent, resume_possible);
7878
}
7979

80+
void KernelNotifications::snapshotLoadProgress(double progress)
81+
{
82+
uiInterface.SnapshotLoadProgress(progress);
83+
}
84+
8085
void KernelNotifications::warningSet(kernel::Warning id, const bilingual_str& message)
8186
{
8287
if (m_warnings.Set(id, message)) {

src/node/kernel_notifications.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class KernelNotifications : public kernel::Notifications
4141

4242
void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override;
4343

44+
void snapshotLoadProgress(double progress) override;
45+
4446
void warningSet(kernel::Warning id, const bilingual_str& message) override;
4547

4648
void warningUnset(kernel::Warning id) override;

src/qt/optionsdialog.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#include <QMessageBox>
3434
#include <QSystemTrayIcon>
3535
#include <QTimer>
36+
#include <QProgressDialog>
37+
38+
#include <interfaces/handler.h>
3639

3740
int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc)
3841
{
@@ -408,29 +411,46 @@ void OptionsDialog::on_showTrayIcon_stateChanged(int state)
408411

409412
void OptionsDialog::on_loadSnapshotButton_clicked()
410413
{
411-
QString snapshotFile = QFileDialog::getOpenFileName(this,
412-
tr("Select Snapshot File"), "",
413-
tr("Bitcoin Snapshot Files (*.dat);;All Files (*)"));
414+
QString filename = QFileDialog::getOpenFileName(this,
415+
tr("Load Snapshot"),
416+
tr("Bitcoin Snapshot Files (*.dat);;"));
414417

415-
if (snapshotFile.isEmpty())
416-
return;
418+
if (filename.isEmpty()) return;
417419

418-
QMessageBox::StandardButton reply = QMessageBox::question(this,
419-
tr("Load Snapshot"),
420-
tr("Loading a snapshot will require restarting Bitcoin. The current blockchain data will be replaced with the snapshot data. Are you sure you want to proceed?"),
421-
QMessageBox::Yes|QMessageBox::No);
422-
423-
if (reply == QMessageBox::Yes) {
424-
SnapshotModel snapshotModel(model->node(), snapshotFile);
425-
if (snapshotModel.processPath()) {
426-
QMessageBox::information(this,
427-
tr("Snapshot loaded successfully"),
428-
tr("The snapshot has been loaded successfully. You can now start the client with the new snapshot."));
429-
} else {
430-
QMessageBox::critical(this,
431-
tr("Error"),
432-
tr("Failed to load the snapshot. Please ensure the file is a valid snapshot and try again."));
433-
}
420+
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm snapshot load"),
421+
tr("Are you sure you want to load this snapshot? This will delete your current blockchain data."),
422+
QMessageBox::Yes | QMessageBox::Cancel,
423+
QMessageBox::Cancel);
424+
425+
if (retval != QMessageBox::Yes) return;
426+
427+
QProgressDialog* progress = new QProgressDialog(tr("Loading snapshot..."), tr("Cancel"), 0, 100, this);
428+
progress->setWindowModality(Qt::WindowModal);
429+
progress->setMinimumDuration(0);
430+
progress->setValue(0);
431+
progress->show();
432+
433+
// Store the handler in the member variable to keep it alive
434+
m_snapshot_load_handler = model->node().handleSnapshotLoadProgress(
435+
[progress](double p) {
436+
progress->setValue(static_cast<int>(p * 100));
437+
QApplication::processEvents();
438+
});
439+
440+
SnapshotModel snapshotModel(model->node(), filename);
441+
bool success = snapshotModel.processPath();
442+
443+
// Clean up the progress dialog
444+
progress->close();
445+
progress->deleteLater();
446+
447+
// Clean up the handler
448+
m_snapshot_load_handler.reset();
449+
450+
if (success) {
451+
QMessageBox::information(this, tr("Success"), tr("Snapshot loaded successfully"));
452+
} else {
453+
QMessageBox::critical(this, tr("Error"), tr("Error loading snapshot"));
434454
}
435455
}
436456

src/qt/optionsdialog.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ namespace Ui {
2020
class OptionsDialog;
2121
}
2222

23+
namespace interfaces {
24+
class Handler;
25+
}
26+
2327
/** Proxy address widget validator, checks for a valid proxy address.
2428
*/
2529
class ProxyAddressValidator : public QValidator
@@ -79,6 +83,7 @@ private Q_SLOTS:
7983
ClientModel* m_client_model{nullptr};
8084
OptionsModel* model{nullptr};
8185
QDataWidgetMapper* mapper{nullptr};
86+
std::unique_ptr<interfaces::Handler> m_snapshot_load_handler;
8287
};
8388

8489
#endif // BITCOIN_QT_OPTIONSDIALOG_H

src/validation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5909,6 +5909,10 @@ util::Result<void> ChainstateManager::PopulateAndValidateSnapshot(
59095909
--coins_left;
59105910
++coins_processed;
59115911

5912+
// Show Snapshot Loading progress
5913+
double progress = static_cast<double>(coins_processed) / static_cast<double>(coins_count);
5914+
GetNotifications().snapshotLoadProgress(progress);
5915+
59125916
if (coins_processed % 1000000 == 0) {
59135917
LogPrintf("[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
59145918
coins_processed,

0 commit comments

Comments
 (0)