Line data Source code
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 <logging.h> 8 : #include <streams.h> 9 : #include <sync.h> 10 : #include <tinyformat.h> 11 : #include <txdb.h> 12 : #include <uint256.h> 13 : #include <util/fs.h> 14 : #include <validation.h> 15 : 16 : #include <cassert> 17 2 : #include <cstdio> 18 2 : #include <optional> 19 : #include <string> 20 : 21 : namespace node { 22 : 23 0 : bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate) 24 : { 25 0 : AssertLockHeld(::cs_main); 26 0 : assert(snapshot_chainstate.m_from_snapshot_blockhash); 27 : 28 0 : const std::optional<fs::path> chaindir = snapshot_chainstate.CoinsDB().StoragePath(); 29 0 : assert(chaindir); // Sanity check that chainstate isn't in-memory. 30 0 : const fs::path write_to = *chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME; 31 : 32 0 : FILE* file{fsbridge::fopen(write_to, "wb")}; 33 0 : AutoFile afile{file}; 34 0 : if (afile.IsNull()) { 35 0 : LogPrintf("[snapshot] failed to open base blockhash file for writing: %s\n", 36 : fs::PathToString(write_to)); 37 0 : return false; 38 : } 39 0 : afile << *snapshot_chainstate.m_from_snapshot_blockhash; 40 : 41 0 : if (afile.fclose() != 0) { 42 0 : LogPrintf("[snapshot] failed to close base blockhash file %s after writing\n", 43 : fs::PathToString(write_to)); 44 0 : return false; 45 : } 46 0 : return true; 47 0 : } 48 : 49 0 : std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir) 50 : { 51 2 : if (!fs::exists(chaindir)) { 52 0 : LogPrintf("[snapshot] cannot read base blockhash: no chainstate dir " 53 : "exists at path %s\n", fs::PathToString(chaindir)); 54 0 : return std::nullopt; 55 : } 56 0 : const fs::path read_from = chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME; 57 0 : const std::string read_from_str = fs::PathToString(read_from); 58 : 59 0 : if (!fs::exists(read_from)) { 60 0 : LogPrintf("[snapshot] snapshot chainstate dir is malformed! no base blockhash file " 61 : "exists at path %s. Try deleting %s and calling loadtxoutset again?\n", 62 : fs::PathToString(chaindir), read_from_str); 63 0 : return std::nullopt; 64 : } 65 : 66 0 : uint256 base_blockhash; 67 0 : FILE* file{fsbridge::fopen(read_from, "rb")}; 68 0 : AutoFile afile{file}; 69 0 : if (afile.IsNull()) { 70 0 : LogPrintf("[snapshot] failed to open base blockhash file for reading: %s\n", 71 : read_from_str); 72 0 : return std::nullopt; 73 : } 74 2 : afile >> base_blockhash; 75 : 76 0 : if (std::fgetc(afile.Get()) != EOF) { 77 0 : LogPrintf("[snapshot] warning: unexpected trailing data in %s\n", read_from_str); 78 0 : } else if (std::ferror(afile.Get())) { 79 0 : LogPrintf("[snapshot] warning: i/o error reading %s\n", read_from_str); 80 0 : } 81 0 : return base_blockhash; 82 0 : } 83 : 84 1 : std::optional<fs::path> FindSnapshotChainstateDir(const fs::path& data_dir) 85 : { 86 : fs::path possible_dir = 87 1 : data_dir / fs::u8path(strprintf("chainstate%s", SNAPSHOT_CHAINSTATE_SUFFIX)); 88 : 89 1 : if (fs::exists(possible_dir)) { 90 0 : return possible_dir; 91 : } 92 1 : return std::nullopt; 93 1 : } 94 : 95 : } // namespace node