Coverage Report

Created: 2026-04-29 19:21

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