|
| 1 | +// Copyright (c) 2022 The Bitcoin Core developers |
| 2 | +// Distributed under the MIT software license, see the accompanying |
| 3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 4 | + |
| 5 | +#include <node/utxo_snapshot.h> |
| 6 | + |
| 7 | +#include <fs.h> |
| 8 | +#include <logging.h> |
| 9 | +#include <streams.h> |
| 10 | +#include <uint256.h> |
| 11 | +#include <validation.h> |
| 12 | + |
| 13 | +#include <cstdio> |
| 14 | +#include <optional> |
| 15 | + |
| 16 | +namespace node { |
| 17 | + |
| 18 | +bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate) |
| 19 | +{ |
| 20 | + AssertLockHeld(::cs_main); |
| 21 | + assert(snapshot_chainstate.m_from_snapshot_blockhash); |
| 22 | + |
| 23 | + const std::optional<fs::path> chaindir = snapshot_chainstate.CoinsDB().StoragePath(); |
| 24 | + assert(chaindir); // Sanity check that chainstate isn't in-memory. |
| 25 | + const fs::path write_to = *chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME; |
| 26 | + |
| 27 | + FILE* file{fsbridge::fopen(write_to, "wb")}; |
| 28 | + AutoFile afile{file}; |
| 29 | + if (afile.IsNull()) { |
| 30 | + LogPrintf("[snapshot] failed to open base blockhash file for writing: %s\n", |
| 31 | + fs::PathToString(write_to)); |
| 32 | + return false; |
| 33 | + } |
| 34 | + afile << *snapshot_chainstate.m_from_snapshot_blockhash; |
| 35 | + |
| 36 | + if (afile.fclose() != 0) { |
| 37 | + LogPrintf("[snapshot] failed to close base blockhash file %s after writing\n", |
| 38 | + fs::PathToString(write_to)); |
| 39 | + return false; |
| 40 | + } |
| 41 | + return true; |
| 42 | +} |
| 43 | + |
| 44 | +std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir) |
| 45 | +{ |
| 46 | + if (!fs::exists(chaindir)) { |
| 47 | + LogPrintf("[snapshot] cannot read base blockhash: no chainstate dir " /* Continued */ |
| 48 | + "exists at path %s\n", fs::PathToString(chaindir)); |
| 49 | + return std::nullopt; |
| 50 | + } |
| 51 | + const fs::path read_from = chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME; |
| 52 | + const std::string read_from_str = fs::PathToString(read_from); |
| 53 | + |
| 54 | + if (!fs::exists(read_from)) { |
| 55 | + LogPrintf("[snapshot] snapshot chainstate dir is malformed! no base blockhash file " /* Continued */ |
| 56 | + "exists at path %s. Try deleting %s and calling loadtxoutset again?\n", |
| 57 | + fs::PathToString(chaindir), read_from_str); |
| 58 | + return std::nullopt; |
| 59 | + } |
| 60 | + |
| 61 | + uint256 base_blockhash; |
| 62 | + FILE* file{fsbridge::fopen(read_from, "rb")}; |
| 63 | + AutoFile afile{file}; |
| 64 | + if (afile.IsNull()) { |
| 65 | + LogPrintf("[snapshot] failed to open base blockhash file for reading: %s\n", |
| 66 | + read_from_str); |
| 67 | + return std::nullopt; |
| 68 | + } |
| 69 | + afile >> base_blockhash; |
| 70 | + |
| 71 | + if (std::fgetc(afile.Get()) != EOF) { |
| 72 | + LogPrintf("[snapshot] warning: unexpected trailing data in %s\n", read_from_str); |
| 73 | + } else if (std::ferror(afile.Get())) { |
| 74 | + LogPrintf("[snapshot] warning: i/o error reading %s\n", read_from_str); |
| 75 | + } |
| 76 | + return base_blockhash; |
| 77 | +} |
| 78 | + |
| 79 | +} // namespace node |
0 commit comments