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