Merge #10114: [tests] sync_with_ping should assert that ping hasn't timed out
[bitcoinplatinum.git] / src / addrdb.cpp
blob224d3921ccbbddb4f2e858d5bd3fe31a541b6eeb
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.
6 #include "addrdb.h"
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"
17 #include <boost/filesystem.hpp>
19 CBanDB::CBanDB()
21 pathBanlist = GetDataDir() / "banlist.dat";
24 bool CBanDB::Write(const banmap_t& banSet)
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);
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;
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());
45 // Write and commit header, data
46 try {
47 fileout << ssBanlist;
49 catch (const std::exception& e) {
50 return error("%s: Serialize or I/O error - %s", __func__, e.what());
52 FileCommit(fileout.Get());
53 fileout.fclose();
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__);
59 return true;
62 bool CBanDB::Read(banmap_t& banSet)
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());
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;
80 // read data and checksum from file
81 try {
82 filein.read((char *)&vchData[0], dataSize);
83 filein >> hashIn;
85 catch (const std::exception& e) {
86 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
88 filein.fclose();
90 CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION);
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__);
97 unsigned char pchMsgTmp[4];
98 try {
99 // de-serialize file header (network specific magic number) and ..
100 ssBanlist >> FLATDATA(pchMsgTmp);
102 // ... verify the network matches ours
103 if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
104 return error("%s: Invalid network magic number", __func__);
106 // de-serialize ban data
107 ssBanlist >> banSet;
109 catch (const std::exception& e) {
110 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
113 return true;
116 CAddrDB::CAddrDB()
118 pathAddr = GetDataDir() / "peers.dat";
121 bool CAddrDB::Write(const CAddrMan& addr)
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);
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;
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());
142 // Write and commit header, data
143 try {
144 fileout << ssPeers;
146 catch (const std::exception& e) {
147 return error("%s: Serialize or I/O error - %s", __func__, e.what());
149 FileCommit(fileout.Get());
150 fileout.fclose();
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__);
156 return true;
159 bool CAddrDB::Read(CAddrMan& addr)
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());
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;
177 // read data and checksum from file
178 try {
179 filein.read((char *)&vchData[0], dataSize);
180 filein >> hashIn;
182 catch (const std::exception& e) {
183 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
185 filein.fclose();
187 CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
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__);
194 return Read(addr, ssPeers);
197 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
199 unsigned char pchMsgTmp[4];
200 try {
201 // de-serialize file header (network specific magic number) and ..
202 ssPeers >> FLATDATA(pchMsgTmp);
204 // ... verify the network matches ours
205 if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
206 return error("%s: Invalid network magic number", __func__);
208 // de-serialize address data into one CAddrMan object
209 ssPeers >> addr;
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());
217 return true;