Branch data 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 : : #include <cstdio>
18 : : #include <optional>
19 : : #include <string>
20 : :
21 : : namespace node {
22 : :
23 : 12 : bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate)
24 : : {
25 : 12 : AssertLockHeld(::cs_main);
26 [ - + ]: 12 : assert(snapshot_chainstate.m_from_snapshot_blockhash);
27 : :
28 [ - + ]: 12 : const std::optional<fs::path> chaindir = snapshot_chainstate.CoinsDB().StoragePath();
29 [ - + ]: 12 : assert(chaindir); // Sanity check that chainstate isn't in-memory.
30 [ + - + - ]: 24 : const fs::path write_to = *chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME;
31 : :
32 [ + - ]: 12 : FILE* file{fsbridge::fopen(write_to, "wb")};
33 [ + - ]: 12 : AutoFile afile{file};
34 [ - + ]: 12 : 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 [ + - ]: 12 : afile << *snapshot_chainstate.m_from_snapshot_blockhash;
40 : :
41 [ + - - + ]: 24 : 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 : : return true;
47 [ + - ]: 36 : }
48 : :
49 : 16 : std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir)
50 : : {
51 [ - + ]: 16 : 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 [ + - ]: 32 : const fs::path read_from = chaindir / node::SNAPSHOT_BLOCKHASH_FILENAME;
57 [ + - ]: 16 : const std::string read_from_str = fs::PathToString(read_from);
58 : :
59 [ + - - + ]: 16 : 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 : 16 : uint256 base_blockhash;
67 [ + - ]: 16 : FILE* file{fsbridge::fopen(read_from, "rb")};
68 [ + - ]: 16 : AutoFile afile{file};
69 [ - + ]: 16 : 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 [ + - ]: 16 : afile >> base_blockhash;
75 : :
76 [ + - ]: 16 : int64_t position = afile.tell();
77 [ + - ]: 16 : afile.seek(0, SEEK_END);
78 [ + - - + ]: 16 : if (position != afile.tell()) {
79 [ # # ]: 0 : LogPrintf("[snapshot] warning: unexpected trailing data in %s\n", read_from_str);
80 : : }
81 : 16 : return base_blockhash;
82 : 48 : }
83 : :
84 : 1123 : std::optional<fs::path> FindSnapshotChainstateDir(const fs::path& data_dir)
85 : : {
86 : 1123 : fs::path possible_dir =
87 [ + - + - ]: 5615 : data_dir / fs::u8path(strprintf("chainstate%s", SNAPSHOT_CHAINSTATE_SUFFIX));
88 : :
89 [ + - + + ]: 1123 : if (fs::exists(possible_dir)) {
90 : 48 : return possible_dir;
91 : : }
92 : 1075 : return std::nullopt;
93 : 1123 : }
94 : :
95 : : } // namespace node
|