|
29 | 29 | #include <node/context.h>
|
30 | 30 | #include <node/interface_ui.h>
|
31 | 31 | #include <node/transaction.h>
|
| 32 | +#include <node/utxo_snapshot.h> |
32 | 33 | #include <policy/feerate.h>
|
33 | 34 | #include <policy/fees.h>
|
34 | 35 | #include <policy/policy.h>
|
@@ -395,6 +396,73 @@ class NodeImpl : public Node
|
395 | 396 | {
|
396 | 397 | m_context = context;
|
397 | 398 | }
|
| 399 | + bool snapshotLoad(const std::string& path_string) override |
| 400 | + { |
| 401 | + fs::path path(fs::u8path(path_string)); |
| 402 | + if (!fs::exists(path)) { |
| 403 | + LogPrintf("[loadsnapshot] snapshot file %s does not exist\n", path.u8string()); |
| 404 | + return false; |
| 405 | + } |
| 406 | + |
| 407 | + FILE* file{fsbridge::fopen(path, "rb")}; |
| 408 | + |
| 409 | + AutoFile afile{file}; |
| 410 | + if (afile.IsNull()) { |
| 411 | + LogPrintf("[loadsnapshot] failed to open snapshot file %s\n", path_string); |
| 412 | + return false; |
| 413 | + } |
| 414 | + |
| 415 | + // Read the snapshot metadata. |
| 416 | + SnapshotMetadata metadata; |
| 417 | + afile >> metadata; |
| 418 | + |
| 419 | + // Get the base blockhash and look up the corresponding CBlockIndex object. |
| 420 | + uint256 base_blockhash = metadata.m_base_blockhash; |
| 421 | + int max_secs_to_wait_for_headers = 60 * 10; |
| 422 | + CBlockIndex* snapshot_start_block = nullptr; |
| 423 | + |
| 424 | + LogPrintf("[loadsnapshot] waiting to see blockheader %s in headers chain before snapshot activation\n", |
| 425 | + base_blockhash.ToString()); |
| 426 | + |
| 427 | + if (m_context->chainman == nullptr) { |
| 428 | + LogPrintf("[loadsnapshot] m_context->chainman is null\n"); |
| 429 | + return false; |
| 430 | + } |
| 431 | + |
| 432 | + ChainstateManager& chainman = *m_context->chainman; |
| 433 | + |
| 434 | + while (max_secs_to_wait_for_headers > 0) { |
| 435 | + LogPrintf("[loadsnapshot] base_blockhash = %s\n", base_blockhash.ToString()); |
| 436 | + snapshot_start_block = WITH_LOCK(::cs_main, |
| 437 | + return chainman.m_blockman.LookupBlockIndex(base_blockhash)); |
| 438 | + max_secs_to_wait_for_headers -= 1; |
| 439 | + |
| 440 | + if (!snapshot_start_block) { |
| 441 | + std::this_thread::sleep_for(std::chrono::seconds(1)); |
| 442 | + } else { |
| 443 | + break; |
| 444 | + } |
| 445 | + } |
| 446 | + |
| 447 | + if (!snapshot_start_block) { |
| 448 | + LogPrintf("[loadsnapshot] timed out waiting for snapshot start blockheader %s\n", |
| 449 | + base_blockhash.ToString()); |
| 450 | + return false; |
| 451 | + } |
| 452 | + |
| 453 | + // Activate the snapshot. |
| 454 | + if (!chainman.ActivateSnapshot(afile, metadata, false)) { |
| 455 | + LogPrintf("[loadsnapshot] Unable to load UTXO snapshot %s\n", path.u8string()); |
| 456 | + return false; |
| 457 | + } |
| 458 | + |
| 459 | + // Get the new tip and print a log message. |
| 460 | + CBlockIndex* new_tip{WITH_LOCK(::cs_main, return chainman.ActiveTip())}; |
| 461 | + LogPrintf("[loadsnashot] Loaded %d coins from snapshot %s at height %d\n", |
| 462 | + metadata.m_coins_count, new_tip->GetBlockHash().ToString(), new_tip->nHeight); |
| 463 | + |
| 464 | + return true; |
| 465 | + } |
398 | 466 | ArgsManager& args() { return *Assert(Assert(m_context)->args); }
|
399 | 467 | ChainstateManager& chainman() { return *Assert(m_context->chainman); }
|
400 | 468 | NodeContext* m_context{nullptr};
|
|
0 commit comments