Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #include <addrdb.h>
# 7 : :
# 8 : : #include <addrman.h>
# 9 : : #include <chainparams.h>
# 10 : : #include <clientversion.h>
# 11 : : #include <cstdint>
# 12 : : #include <hash.h>
# 13 : : #include <logging/timer.h>
# 14 : : #include <random.h>
# 15 : : #include <streams.h>
# 16 : : #include <tinyformat.h>
# 17 : : #include <util/system.h>
# 18 : :
# 19 : : namespace {
# 20 : :
# 21 : : template <typename Stream, typename Data>
# 22 : : bool SerializeDB(Stream& stream, const Data& data)
# 23 : 2185 : {
# 24 : : // Write and commit header, data
# 25 : 2185 : try {
# 26 : 2185 : CHashWriter hasher(SER_DISK, CLIENT_VERSION);
# 27 : 2185 : stream << Params().MessageStart() << data;
# 28 : 2185 : hasher << Params().MessageStart() << data;
# 29 : 2185 : stream << hasher.GetHash();
# 30 : 2185 : } catch (const std::exception& e) {
# 31 : 0 : return error("%s: Serialize or I/O error - %s", __func__, e.what());
# 32 : 0 : }
# 33 : :
# 34 : 2185 : return true;
# 35 : 2185 : }
# 36 : :
# 37 : : template <typename Data>
# 38 : : bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
# 39 : 2185 : {
# 40 : : // Generate random temporary filename
# 41 : 2185 : uint16_t randv = 0;
# 42 : 2185 : GetRandBytes((unsigned char*)&randv, sizeof(randv));
# 43 : 2185 : std::string tmpfn = strprintf("%s.%04x", prefix, randv);
# 44 : :
# 45 : : // open temp output file, and associate with CAutoFile
# 46 : 2185 : fs::path pathTmp = gArgs.GetDataDirNet() / tmpfn;
# 47 : 2185 : FILE *file = fsbridge::fopen(pathTmp, "wb");
# 48 : 2185 : CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
# 49 [ - + ][ - + ]: 2185 : if (fileout.IsNull()) {
# [ - + ]
# 50 : 0 : fileout.fclose();
# 51 : 0 : remove(pathTmp);
# 52 : 0 : return error("%s: Failed to open file %s", __func__, pathTmp.string());
# 53 : 0 : }
# 54 : :
# 55 : : // Serialize
# 56 [ - + ][ - + ]: 2185 : if (!SerializeDB(fileout, data)) {
# [ - + ]
# 57 : 0 : fileout.fclose();
# 58 : 0 : remove(pathTmp);
# 59 : 0 : return false;
# 60 : 0 : }
# 61 [ - + ][ - + ]: 2185 : if (!FileCommit(fileout.Get())) {
# [ - + ]
# 62 : 0 : fileout.fclose();
# 63 : 0 : remove(pathTmp);
# 64 : 0 : return error("%s: Failed to flush file %s", __func__, pathTmp.string());
# 65 : 0 : }
# 66 : 2185 : fileout.fclose();
# 67 : :
# 68 : : // replace existing file, if any, with new file
# 69 [ - + ][ - + ]: 2185 : if (!RenameOver(pathTmp, path)) {
# [ - + ]
# 70 : 0 : remove(pathTmp);
# 71 : 0 : return error("%s: Rename-into-place failed", __func__);
# 72 : 0 : }
# 73 : :
# 74 : 2185 : return true;
# 75 : 2185 : }
# 76 : :
# 77 : : template <typename Stream, typename Data>
# 78 : : bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
# 79 : 765 : {
# 80 : 765 : try {
# 81 : 765 : CHashVerifier<Stream> verifier(&stream);
# 82 : : // de-serialize file header (network specific magic number) and ..
# 83 : 765 : unsigned char pchMsgTmp[4];
# 84 : 765 : verifier >> pchMsgTmp;
# 85 : : // ... verify the network matches ours
# 86 [ - + ][ - + ]: 765 : if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
# [ - + ][ - + ]
# 87 : 0 : return error("%s: Invalid network magic number", __func__);
# 88 : :
# 89 : : // de-serialize data
# 90 : 765 : verifier >> data;
# 91 : :
# 92 : : // verify checksum
# 93 [ + - ][ + - ]: 765 : if (fCheckSum) {
# [ - + ][ + - ]
# 94 : 761 : uint256 hashTmp;
# 95 : 761 : stream >> hashTmp;
# 96 [ - + ][ - + ]: 761 : if (hashTmp != verifier.GetHash()) {
# [ # # ][ - + ]
# 97 : 0 : return error("%s: Checksum mismatch, data corrupted", __func__);
# 98 : 0 : }
# 99 : 2 : }
# 100 : 765 : }
# 101 : 2 : catch (const std::exception& e) {
# 102 : 2 : return error("%s: Deserialize or I/O error - %s", __func__, e.what());
# 103 : 2 : }
# 104 : :
# 105 : 763 : return true;
# 106 : 763 : }
# 107 : :
# 108 : : template <typename Data>
# 109 : : bool DeserializeFileDB(const fs::path& path, Data& data)
# 110 : 2029 : {
# 111 : : // open input file, and associate with CAutoFile
# 112 : 2029 : FILE* file = fsbridge::fopen(path, "rb");
# 113 : 2029 : CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
# 114 [ + + ][ + + ]: 2029 : if (filein.IsNull()) {
# [ + + ]
# 115 : 1268 : LogPrintf("Missing or invalid file %s\n", path.string());
# 116 : 1268 : return false;
# 117 : 1268 : }
# 118 : 761 : return DeserializeDB(filein, data);
# 119 : 761 : }
# 120 : : } // namespace
# 121 : :
# 122 : : CBanDB::CBanDB(fs::path ban_list_path) : m_ban_list_path(std::move(ban_list_path))
# 123 : 794 : {
# 124 : 794 : }
# 125 : :
# 126 : : bool CBanDB::Write(const banmap_t& banSet)
# 127 : 573 : {
# 128 : 573 : return SerializeFileDB("banlist", m_ban_list_path, banSet);
# 129 : 573 : }
# 130 : :
# 131 : : bool CBanDB::Read(banmap_t& banSet)
# 132 : 794 : {
# 133 : 794 : return DeserializeFileDB(m_ban_list_path, banSet);
# 134 : 794 : }
# 135 : :
# 136 : : CAddrDB::CAddrDB()
# 137 : 1613 : {
# 138 : 1613 : pathAddr = gArgs.GetDataDirNet() / "peers.dat";
# 139 : 1613 : }
# 140 : :
# 141 : : bool CAddrDB::Write(const CAddrMan& addr)
# 142 : 995 : {
# 143 : 995 : return SerializeFileDB("peers", pathAddr, addr);
# 144 : 995 : }
# 145 : :
# 146 : : bool CAddrDB::Read(CAddrMan& addr)
# 147 : 618 : {
# 148 : 618 : return DeserializeFileDB(pathAddr, addr);
# 149 : 618 : }
# 150 : :
# 151 : : bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
# 152 : 4 : {
# 153 : 4 : bool ret = DeserializeDB(ssPeers, addr, false);
# 154 [ + + ]: 4 : if (!ret) {
# 155 : : // Ensure addrman is left in a clean state
# 156 : 2 : addr.Clear();
# 157 : 2 : }
# 158 : 4 : return ret;
# 159 : 4 : }
# 160 : :
# 161 : : void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
# 162 : 617 : {
# 163 : 617 : LOG_TIME_SECONDS(strprintf("Flush %d outbound block-relay-only peer addresses to anchors.dat", anchors.size()));
# 164 : 617 : SerializeFileDB("anchors", anchors_db_path, anchors);
# 165 : 617 : }
# 166 : :
# 167 : : std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
# 168 : 617 : {
# 169 : 617 : std::vector<CAddress> anchors;
# 170 [ + + ]: 617 : if (DeserializeFileDB(anchors_db_path, anchors)) {
# 171 : 246 : LogPrintf("Loaded %i addresses from %s\n", anchors.size(), anchors_db_path.filename());
# 172 : 371 : } else {
# 173 : 371 : anchors.clear();
# 174 : 371 : }
# 175 : :
# 176 : 617 : fs::remove(anchors_db_path);
# 177 : 617 : return anchors;
# 178 : 617 : }
|