Dogecoin Core  1.14.2
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.h"
16 
17 #include <boost/filesystem.hpp>
18 
20 {
21  pathBanlist = GetDataDir() / "banlist.dat";
22 }
23 
24 bool CBanDB::Write(const banmap_t& banSet)
25 {
26  // Generate random temporary filename
27  unsigned short randv = 0;
28  GetRandBytes((unsigned char*)&randv, sizeof(randv));
29  std::string tmpfn = strprintf("banlist.dat.%04x", randv);
30 
31  // serialize banlist, checksum data up to that point, then append csum
32  CDataStream ssBanlist(SER_DISK, CLIENT_VERSION);
33  ssBanlist << FLATDATA(Params().MessageStart());
34  ssBanlist << banSet;
35  uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end());
36  ssBanlist << hash;
37 
38  // open temp output file, and associate with CAutoFile
39  boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
40  FILE *file = fopen(pathTmp.string().c_str(), "wb");
41  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
42  if (fileout.IsNull())
43  return error("%s: Failed to open file %s", __func__, pathTmp.string());
44 
45  // Write and commit header, data
46  try {
47  fileout << ssBanlist;
48  }
49  catch (const std::exception& e) {
50  return error("%s: Serialize or I/O error - %s", __func__, e.what());
51  }
52  FileCommit(fileout.Get());
53  fileout.fclose();
54 
55  // replace existing banlist.dat, if any, with new banlist.dat.XXXX
56  if (!RenameOver(pathTmp, pathBanlist))
57  return error("%s: Rename-into-place failed", __func__);
58 
59  return true;
60 }
61 
62 bool CBanDB::Read(banmap_t& banSet)
63 {
64  // open input file, and associate with CAutoFile
65  FILE *file = fopen(pathBanlist.string().c_str(), "rb");
66  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
67  if (filein.IsNull())
68  return error("%s: Failed to open file %s", __func__, pathBanlist.string());
69 
70  // use file size to size memory buffer
71  uint64_t fileSize = boost::filesystem::file_size(pathBanlist);
72  uint64_t dataSize = 0;
73  // Don't try to resize to a negative number if file is small
74  if (fileSize >= sizeof(uint256))
75  dataSize = fileSize - sizeof(uint256);
76  std::vector<unsigned char> vchData;
77  vchData.resize(dataSize);
78  uint256 hashIn;
79 
80  // read data and checksum from file
81  try {
82  filein.read((char *)&vchData[0], dataSize);
83  filein >> hashIn;
84  }
85  catch (const std::exception& e) {
86  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
87  }
88  filein.fclose();
89 
90  CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION);
91 
92  // verify stored checksum matches input data
93  uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end());
94  if (hashIn != hashTmp)
95  return error("%s: Checksum mismatch, data corrupted", __func__);
96 
97  unsigned char pchMsgTmp[4];
98  try {
99  // de-serialize file header (network specific magic number) and ..
100  ssBanlist >> FLATDATA(pchMsgTmp);
101 
102  // ... verify the network matches ours
103  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
104  return error("%s: Invalid network magic number", __func__);
105 
106  // de-serialize ban data
107  ssBanlist >> banSet;
108  }
109  catch (const std::exception& e) {
110  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
111  }
112 
113  return true;
114 }
115 
117 {
118  pathAddr = GetDataDir() / "peers.dat";
119 }
120 
121 bool CAddrDB::Write(const CAddrMan& addr)
122 {
123  // Generate random temporary filename
124  unsigned short randv = 0;
125  GetRandBytes((unsigned char*)&randv, sizeof(randv));
126  std::string tmpfn = strprintf("peers.dat.%04x", randv);
127 
128  // serialize addresses, checksum data up to that point, then append csum
129  CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
130  ssPeers << FLATDATA(Params().MessageStart());
131  ssPeers << addr;
132  uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
133  ssPeers << hash;
134 
135  // open temp output file, and associate with CAutoFile
136  boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
137  FILE *file = fopen(pathTmp.string().c_str(), "wb");
138  CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
139  if (fileout.IsNull())
140  return error("%s: Failed to open file %s", __func__, pathTmp.string());
141 
142  // Write and commit header, data
143  try {
144  fileout << ssPeers;
145  }
146  catch (const std::exception& e) {
147  return error("%s: Serialize or I/O error - %s", __func__, e.what());
148  }
149  FileCommit(fileout.Get());
150  fileout.fclose();
151 
152  // replace existing peers.dat, if any, with new peers.dat.XXXX
153  if (!RenameOver(pathTmp, pathAddr))
154  return error("%s: Rename-into-place failed", __func__);
155 
156  return true;
157 }
158 
160 {
161  // open input file, and associate with CAutoFile
162  FILE *file = fopen(pathAddr.string().c_str(), "rb");
163  CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
164  if (filein.IsNull())
165  return error("%s: Failed to open file %s", __func__, pathAddr.string());
166 
167  // use file size to size memory buffer
168  uint64_t fileSize = boost::filesystem::file_size(pathAddr);
169  uint64_t dataSize = 0;
170  // Don't try to resize to a negative number if file is small
171  if (fileSize >= sizeof(uint256))
172  dataSize = fileSize - sizeof(uint256);
173  std::vector<unsigned char> vchData;
174  vchData.resize(dataSize);
175  uint256 hashIn;
176 
177  // read data and checksum from file
178  try {
179  filein.read((char *)&vchData[0], dataSize);
180  filein >> hashIn;
181  }
182  catch (const std::exception& e) {
183  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
184  }
185  filein.fclose();
186 
187  CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
188 
189  // verify stored checksum matches input data
190  uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
191  if (hashIn != hashTmp)
192  return error("%s: Checksum mismatch, data corrupted", __func__);
193 
194  return Read(addr, ssPeers);
195 }
196 
197 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
198 {
199  unsigned char pchMsgTmp[4];
200  try {
201  // de-serialize file header (network specific magic number) and ..
202  ssPeers >> FLATDATA(pchMsgTmp);
203 
204  // ... verify the network matches ours
205  if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
206  return error("%s: Invalid network magic number", __func__);
207 
208  // de-serialize address data into one CAddrMan object
209  ssPeers >> addr;
210  }
211  catch (const std::exception& e) {
212  // de-serialization has failed, ensure addrman is left in a clean state
213  addr.Clear();
214  return error("%s: Deserialize or I/O error - %s", __func__, e.what());
215  }
216 
217  return true;
218 }
std::map< CSubNet, CBanEntry > banmap_t
Definition: addrdb.h:77
const CChainParams & Params()
Return the currently selected parameters.
bool Write(const CAddrMan &addr)
Definition: addrdb.cpp:121
bool Read(CAddrMan &addr)
Definition: addrdb.cpp:159
CAddrDB()
Definition: addrdb.cpp:116
boost::filesystem::path pathAddr
Definition: addrdb.h:83
Stochastical (IP) address manager.
Definition: addrman.h:178
void Clear()
Definition: addrman.h:451
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:456
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
Definition: streams.h:496
bool IsNull() const
Return true if the wrapped FILE* is NULL, false otherwise.
Definition: streams.h:500
void fclose()
Definition: streams.h:478
void read(char *pch, size_t nSize)
Definition: streams.h:508
bool Write(const banmap_t &banSet)
Definition: addrdb.cpp:24
boost::filesystem::path pathBanlist
Definition: addrdb.h:95
bool Read(banmap_t &banSet)
Definition: addrdb.cpp:62
CBanDB()
Definition: addrdb.cpp:19
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
const_iterator begin() const
Definition: streams.h:233
const_iterator end() const
Definition: streams.h:235
256-bit opaque blob.
Definition: uint256.h:123
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:70
void GetRandBytes(unsigned char *buf, int num)
Functions to gather random data via the OpenSSL PRNG.
Definition: random.cpp:125
@ SER_DISK
Definition: serialize.h:147
#define FLATDATA(obj)
Definition: serialize.h:347
#define strprintf
Definition: tinyformat.h:1047
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:513
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
Definition: util.cpp:605
void FileCommit(FILE *file)
Definition: util.cpp:635
bool error(const char *fmt, const Args &... args)
Definition: util.h:87