mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
validation: rename snapshot chainstate dir
This changes the snapshot's leveldb chainstate dir name from `chainstate_[blockhash]` to `chainstate_snapshot`. This simplifies later logic that loads snapshot data, and enforces the limitation of a single snapshot at any given time. Since we still need to persis the blockhash of the base block, we write that out to a file (`chainstate_snapshot/base_blockhash`) for later use during initialization, so that we can reinitialize the snapshot chainstate. Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
This commit is contained in:
79
src/node/utxo_snapshot.cpp
Normal file
79
src/node/utxo_snapshot.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2022 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <node/utxo_snapshot.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <logging.h>
|
||||
#include <streams.h>
|
||||
#include <uint256.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
|
||||
namespace node {
|
||||
|
||||
bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
assert(snapshot_chainstate.m_from_snapshot_blockhash);
|
||||
|
||||
const std::optional<fs::path> chaindir = snapshot_chainstate.CoinsDB().StoragePath();
|
||||
assert(chaindir); // Sanity check that chainstate isn't in-memory.
|
||||
const fs::path write_to = *chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME;
|
||||
|
||||
FILE* file{fsbridge::fopen(write_to, "wb")};
|
||||
AutoFile afile{file};
|
||||
if (afile.IsNull()) {
|
||||
LogPrintf("[snapshot] failed to open base blockhash file for writing: %s\n",
|
||||
fs::PathToString(write_to));
|
||||
return false;
|
||||
}
|
||||
afile << *snapshot_chainstate.m_from_snapshot_blockhash;
|
||||
|
||||
if (afile.fclose() != 0) {
|
||||
LogPrintf("[snapshot] failed to close base blockhash file %s after writing\n",
|
||||
fs::PathToString(write_to));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir)
|
||||
{
|
||||
if (!fs::exists(chaindir)) {
|
||||
LogPrintf("[snapshot] cannot read base blockhash: no chainstate dir " /* Continued */
|
||||
"exists at path %s\n", fs::PathToString(chaindir));
|
||||
return std::nullopt;
|
||||
}
|
||||
const fs::path read_from = chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME;
|
||||
const std::string read_from_str = fs::PathToString(read_from);
|
||||
|
||||
if (!fs::exists(read_from)) {
|
||||
LogPrintf("[snapshot] snapshot chainstate dir is malformed! no base blockhash file " /* Continued */
|
||||
"exists at path %s. Try deleting %s and calling loadtxoutset again?\n",
|
||||
fs::PathToString(chaindir), read_from_str);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint256 base_blockhash;
|
||||
FILE* file{fsbridge::fopen(read_from, "rb")};
|
||||
AutoFile afile{file};
|
||||
if (afile.IsNull()) {
|
||||
LogPrintf("[snapshot] failed to open base blockhash file for reading: %s\n",
|
||||
read_from_str);
|
||||
return std::nullopt;
|
||||
}
|
||||
afile >> base_blockhash;
|
||||
|
||||
if (std::fgetc(afile.Get()) != EOF) {
|
||||
LogPrintf("[snapshot] warning: unexpected trailing data in %s\n", read_from_str);
|
||||
} else if (std::ferror(afile.Get())) {
|
||||
LogPrintf("[snapshot] warning: i/o error reading %s\n", read_from_str);
|
||||
}
|
||||
return base_blockhash;
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
@@ -6,8 +6,14 @@
|
||||
#ifndef BITCOIN_NODE_UTXO_SNAPSHOT_H
|
||||
#define BITCOIN_NODE_UTXO_SNAPSHOT_H
|
||||
|
||||
#include <fs.h>
|
||||
#include <uint256.h>
|
||||
#include <serialize.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
extern RecursiveMutex cs_main;
|
||||
|
||||
namespace node {
|
||||
//! Metadata describing a serialized version of a UTXO set from which an
|
||||
@@ -33,6 +39,27 @@ public:
|
||||
|
||||
SERIALIZE_METHODS(SnapshotMetadata, obj) { READWRITE(obj.m_base_blockhash, obj.m_coins_count); }
|
||||
};
|
||||
|
||||
//! The file in the snapshot chainstate dir which stores the base blockhash. This is
|
||||
//! needed to reconstruct snapshot chainstates on init.
|
||||
//!
|
||||
//! Because we only allow loading a single snapshot at a time, there will only be one
|
||||
//! chainstate directory with this filename present within it.
|
||||
const fs::path SNAPSHOT_BLOCKHASH_FILENAME{"base_blockhash"};
|
||||
|
||||
//! Write out the blockhash of the snapshot base block that was used to construct
|
||||
//! this chainstate. This value is read in during subsequent initializations and
|
||||
//! used to reconstruct snapshot-based chainstates.
|
||||
bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
//! Read the blockhash of the snapshot base block that was used to construct the
|
||||
//! chainstate.
|
||||
std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
constexpr std::string_view SNAPSHOT_CHAINSTATE_SUFFIX = "_snapshot";
|
||||
|
||||
} // namespace node
|
||||
|
||||
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H
|
||||
|
||||
Reference in New Issue
Block a user