1818#include < interfaces/handler.h>
1919#include < interfaces/mining.h>
2020#include < interfaces/node.h>
21+ #include < interfaces/snapshot.h>
2122#include < interfaces/types.h>
2223#include < interfaces/wallet.h>
2324#include < kernel/chain.h>
3839#include < node/kernel_notifications.h>
3940#include < node/transaction.h>
4041#include < node/types.h>
42+ #include < node/utxo_snapshot.h>
4143#include < node/warnings.h>
4244#include < policy/feerate.h>
4345#include < policy/fees.h>
@@ -80,6 +82,7 @@ using interfaces::Handler;
8082using interfaces::MakeSignalHandler;
8183using interfaces::Mining;
8284using interfaces::Node;
85+ using interfaces::Snapshot;
8386using interfaces::WalletLoader;
8487using node::BlockAssembler;
8588using node::BlockWaitOptions;
@@ -89,6 +92,73 @@ namespace node {
8992// All members of the classes in this namespace are intentionally public, as the
9093// classes themselves are private.
9194namespace {
95+ class SnapshotImpl : public interfaces ::Snapshot
96+ {
97+ public:
98+ SnapshotImpl (ChainstateManager& chainman, const fs::path& path, bool in_memory)
99+ : m_chainman(chainman), m_path(path), m_in_memory(in_memory), m_metadata(chainman.GetParams().MessageStart()) {}
100+
101+ bool activate () override
102+ {
103+ m_last_error.clear ();
104+
105+ if (!fs::exists (m_path)) {
106+ m_last_error = " Snapshot file does not exist" ;
107+ return false ;
108+ }
109+
110+ FILE* snapshot_file{fsbridge::fopen (m_path, " rb" )};
111+ AutoFile afile{snapshot_file};
112+ if (afile.IsNull ()) {
113+ m_last_error = " Unable to open snapshot file for reading" ;
114+ return false ;
115+ }
116+
117+ try {
118+ afile >> m_metadata;
119+ } catch (const std::ios_base::failure& e) {
120+ m_last_error = strprintf (" Unable to parse metadata: %s" , e.what ());
121+ return false ;
122+ }
123+
124+ auto result = m_chainman.ActivateSnapshot (afile, m_metadata, m_in_memory);
125+ if (result.has_value ()) {
126+ m_activation_result = result.value ();
127+ return true ;
128+ } else {
129+ m_activation_result = std::nullopt ;
130+ m_last_error = util::ErrorString (result).original ;
131+ return false ;
132+ }
133+ }
134+
135+ const node::SnapshotMetadata& getMetadata () const override
136+ {
137+ return m_metadata;
138+ }
139+
140+ std::optional<const CBlockIndex*> getActivationResult () const override
141+ {
142+ if (m_activation_result.has_value ()) {
143+ return m_activation_result;
144+ }
145+ return std::nullopt ;
146+ }
147+
148+ std::string getLastError () const override
149+ {
150+ return m_last_error;
151+ }
152+
153+ private:
154+ ChainstateManager& m_chainman;
155+ fs::path m_path;
156+ bool m_in_memory;
157+ node::SnapshotMetadata m_metadata;
158+ std::optional<const CBlockIndex*> m_activation_result;
159+ std::string m_last_error;
160+ };
161+
92162#ifdef ENABLE_EXTERNAL_SIGNER
93163class ExternalSignerImpl : public interfaces ::ExternalSigner
94164{
@@ -356,6 +426,10 @@ class NodeImpl : public Node
356426 return ::tableRPC.execute (req);
357427 }
358428 std::vector<std::string> listRpcCommands () override { return ::tableRPC.listCommands (); }
429+ std::unique_ptr<interfaces::Snapshot> snapshot (const fs::path& path) override
430+ {
431+ return std::make_unique<SnapshotImpl>(chainman (), path, /* in_memory=*/ false );
432+ }
359433 std::optional<Coin> getUnspentOutput (const COutPoint& output) override
360434 {
361435 LOCK (::cs_main);
@@ -385,6 +459,10 @@ class NodeImpl : public Node
385459 {
386460 return MakeSignalHandler (::uiInterface.ShowProgress_connect (fn));
387461 }
462+ std::unique_ptr<Handler> handleSnapshotLoadProgress (SnapshotLoadProgressFn fn) override
463+ {
464+ return MakeSignalHandler (::uiInterface.SnapshotLoadProgress_connect (fn));
465+ }
388466 std::unique_ptr<Handler> handleInitWallet (InitWalletFn fn) override
389467 {
390468 return MakeSignalHandler (::uiInterface.InitWallet_connect (fn));
0 commit comments