Bitcoin Core  0.20.99
P2P Digital Currency
addrdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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 <random.h>
14 #include <streams.h>
15 #include <tinyformat.h>
16 #include <util/system.h>
17 
18 namespace {
19 
20 template <typename Stream, typename Data>
21 bool SerializeDB(Stream& stream, const Data& data)
22 {
23  // Write and commit header, data
24  try {
26  stream << Params().MessageStart() << data;
27  hasher << Params().MessageStart() << data;
28  stream << hasher.GetHash();
29  } catch (const std::exception& e) {
30  return error("%s: Serialize or I/O error - %s", __func__, e.what());
31  }
32 
33  return true;
34 }
35 
36 template <typename Data>
37 bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
38 {
39  // Generate random temporary filename
40  uint16_t randv = 0;
41  GetRandBytes((unsigned char*)&randv, sizeof(randv));
42  std::string tmpfn = strprintf("%s.%04x", prefix, randv);
43 
44  // open temp output file, and associate with CAutoFile
45  fs::path pathTmp = GetDataDir() / tmpfn;
46  FILE *file = fsbridge::fopen(pathTmp, "wb");
47  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
48  if (fileout.IsNull()) {
49  fileout.fclose();
50  remove(pathTmp);
51  return error("%s: Failed to open file %s", __func__, pathTmp.string());
52  }
53 
54  // Serialize
55  if (!SerializeDB(fileout, data)) {
56  fileout.fclose();
57  remove(pathTmp);
58  return false;
59  }
60  if (!FileCommit(fileout.Get())) {
61  fileout.fclose();
62  remove(pathTmp);
63  return error("%s: Failed to flush file %s", __func__, pathTmp.string());
64  }
65  fileout.fclose();
66 
67  // replace existing file, if any, with new file
68  if (!RenameOver(pathTmp, path)) {
69  remove(pathTmp);
70  return error("%s: Rename-into-place failed", __func__);
71  }
72 
73  return true;
74 }
75 
76 template <typename Stream, typename Data>
77 bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
78 {
79  try {
80  CHashVerifier<Stream> verifier(&stream);
81  // de-serialize file header (network specific magic number) and ..
82  unsigned char pchMsgTmp[4];
83  verifier >> pchMsgTmp;
84  // ... verify the network matches ours
85  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
86  return error("%s: Invalid network magic number", __func__);
87 
88  // de-serialize data
89  verifier >> data;
90 
91  // verify checksum
92  if (fCheckSum) {
93  uint256 hashTmp;
94  stream >> hashTmp;
95  if (hashTmp != verifier.GetHash()) {
96  return error("%s: Checksum mismatch, data corrupted", __func__);
97  }
98  }
99  }
100  catch (const std::exception& e) {
101  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
102  }
103 
104  return true;
105 }
106 
107 template <typename Data>
108 bool DeserializeFileDB(const fs::path& path, Data& data)
109 {
110  // open input file, and associate with CAutoFile
111  FILE *file = fsbridge::fopen(path, "rb");
112  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
113  if (filein.IsNull())
114  return error("%s: Failed to open file %s", __func__, path.string());
115 
116  return DeserializeDB(filein, data);
117 }
118 
119 }
120 
121 CBanDB::CBanDB(fs::path ban_list_path) : m_ban_list_path(std::move(ban_list_path))
122 {
123 }
124 
125 bool CBanDB::Write(const banmap_t& banSet)
126 {
127  return SerializeFileDB("banlist", m_ban_list_path, banSet);
128 }
129 
130 bool CBanDB::Read(banmap_t& banSet)
131 {
132  return DeserializeFileDB(m_ban_list_path, banSet);
133 }
134 
136 {
137  pathAddr = GetDataDir() / "peers.dat";
138 }
139 
140 bool CAddrDB::Write(const CAddrMan& addr)
141 {
142  return SerializeFileDB("peers", pathAddr, addr);
143 }
144 
146 {
147  return DeserializeFileDB(pathAddr, addr);
148 }
149 
150 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
151 {
152  bool ret = DeserializeDB(ssPeers, addr, false);
153  if (!ret) {
154  // Ensure addrman is left in a clean state
155  addr.Clear();
156  }
157  return ret;
158 }
bool FileCommit(FILE *file)
Definition: system.cpp:1015
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:24
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
CAddrDB()
Definition: addrdb.cpp:135
const char * prefix
Definition: rest.cpp:670
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:201
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:579
const fs::path m_ban_list_path
Definition: addrdb.h:69
Reads data from an underlying stream, while hashing the read data.
Definition: hash.h:142
Stochastical (IP) address manager.
Definition: addrman.h:176
bool Write(const CAddrMan &addr)
Definition: addrdb.cpp:140
CBanDB(fs::path ban_list_path)
Definition: addrdb.cpp:121
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:703
const CMessageHeader::MessageStartChars & MessageStart() const
Definition: chainparams.h:61
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:125
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:985
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:130
256-bit opaque blob.
Definition: uint256.h:123
void Clear()
Definition: addrman.h:502
const CChainParams & Params()
Return the currently selected parameters.
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:98
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
bool error(const char *fmt, const Args &... args)
Definition: system.h:52
bool Read(CAddrMan &addr)
Definition: addrdb.cpp:145
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:601