Merge #11221: Refactor: simpler read
[bitcoinplatinum.git] / src / addrdb.cpp
blob7f85c16585aa28b471d16c15b689ba23da6391a8
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 "fs.h"
12 #include "hash.h"
13 #include "random.h"
14 #include "streams.h"
15 #include "tinyformat.h"
16 #include "util.h"
18 namespace {
20 template <typename Stream, typename Data>
21 bool SerializeDB(Stream& stream, const Data& data)
23 // Write and commit header, data
24 try {
25 CHashWriter hasher(SER_DISK, CLIENT_VERSION);
26 stream << FLATDATA(Params().MessageStart()) << data;
27 hasher << FLATDATA(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());
33 return true;
36 template <typename Data>
37 bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
39 // Generate random temporary filename
40 unsigned short randv = 0;
41 GetRandBytes((unsigned char*)&randv, sizeof(randv));
42 std::string tmpfn = strprintf("%s.%04x", prefix, randv);
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 return error("%s: Failed to open file %s", __func__, pathTmp.string());
51 // Serialize
52 if (!SerializeDB(fileout, data)) return false;
53 FileCommit(fileout.Get());
54 fileout.fclose();
56 // replace existing file, if any, with new file
57 if (!RenameOver(pathTmp, path))
58 return error("%s: Rename-into-place failed", __func__);
60 return true;
63 template <typename Stream, typename Data>
64 bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
66 try {
67 CHashVerifier<Stream> verifier(&stream);
68 // de-serialize file header (network specific magic number) and ..
69 unsigned char pchMsgTmp[4];
70 verifier >> FLATDATA(pchMsgTmp);
71 // ... verify the network matches ours
72 if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
73 return error("%s: Invalid network magic number", __func__);
75 // de-serialize data
76 verifier >> data;
78 // verify checksum
79 if (fCheckSum) {
80 uint256 hashTmp;
81 stream >> hashTmp;
82 if (hashTmp != verifier.GetHash()) {
83 return error("%s: Checksum mismatch, data corrupted", __func__);
87 catch (const std::exception& e) {
88 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
91 return true;
94 template <typename Data>
95 bool DeserializeFileDB(const fs::path& path, Data& data)
97 // open input file, and associate with CAutoFile
98 FILE *file = fsbridge::fopen(path, "rb");
99 CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
100 if (filein.IsNull())
101 return error("%s: Failed to open file %s", __func__, path.string());
103 return DeserializeDB(filein, data);
108 CBanDB::CBanDB()
110 pathBanlist = GetDataDir() / "banlist.dat";
113 bool CBanDB::Write(const banmap_t& banSet)
115 return SerializeFileDB("banlist", pathBanlist, banSet);
118 bool CBanDB::Read(banmap_t& banSet)
120 return DeserializeFileDB(pathBanlist, banSet);
123 CAddrDB::CAddrDB()
125 pathAddr = GetDataDir() / "peers.dat";
128 bool CAddrDB::Write(const CAddrMan& addr)
130 return SerializeFileDB("peers", pathAddr, addr);
133 bool CAddrDB::Read(CAddrMan& addr)
135 return DeserializeFileDB(pathAddr, addr);
138 bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
140 bool ret = DeserializeDB(ssPeers, addr, false);
141 if (!ret) {
142 // Ensure addrman is left in a clean state
143 addr.Clear();
145 return ret;