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